diff --git a/PcgsInvUi/Services/Database.cs b/PcgsInvUi/Services/Database.cs index ad28908..5e8d3eb 100644 --- a/PcgsInvUi/Services/Database.cs +++ b/PcgsInvUi/Services/Database.cs @@ -121,6 +121,55 @@ public class Database { return coins; } + + public String CollectionToCSV(string collectionName) { + var cmd = Connection.CreateCommand(); + cmd.CommandText = $"SELECT * FROM {collectionName}"; + + var headersCommand = Connection.CreateCommand(); + headersCommand.CommandText = $"PRAGMA table_info({collectionName})"; + + var resultString = ""; + var numHeaders = 0; + + // Get the headers. + using (var reader = headersCommand.ExecuteReader()) { + while (reader.Read()) { + resultString += reader.GetString(1) + ","; + numHeaders++; + } + } + + resultString += "\n"; + + // Is there a more efficient way of doing this? This is running at O(n^2) time. + using (var reader = cmd.ExecuteReader()) { + while (reader.Read()) { + // Read information from the reader, then add to CSV string. + for (int i = 0; i < numHeaders; i++) { + // Get the type of each column. + var type = reader.GetFieldType(i); + Console.WriteLine("Type: " + type); + if (type == typeof(Int64)) { + resultString += reader.GetInt32(i) + ","; + } + else if (type == typeof(Double)) { + resultString += reader.GetDouble(i) + ","; + } + else if (type == typeof(String)) { + resultString += reader.GetString(i) + ","; + } + else { + resultString += "NULL" + ","; + } + } + + resultString += "\n"; + } + } + + return resultString; + } public Coin? GetCoin(int pcgsNumber, string grade) { // Get the coin based off of the pcgs number. diff --git a/PcgsInvUi/ViewModels/MainWindowViewModel.cs b/PcgsInvUi/ViewModels/MainWindowViewModel.cs index 6fd3ade..2b02464 100644 --- a/PcgsInvUi/ViewModels/MainWindowViewModel.cs +++ b/PcgsInvUi/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Reactive; using System.Reactive.Linq; @@ -9,8 +10,6 @@ using ReactiveUI; namespace PcgsInvUi.ViewModels; -// TODO Find window. -// TODO Export window and export function. // TODO Error handling. // TODO Manual handling of API key. // TODO Use CoinFacts link. @@ -43,6 +42,8 @@ public class MainWindowViewModel : ViewModelBase { public Interaction ShowDeleteWindow { get; } public ReactiveCommand FindCommand { get; } public Interaction ShowFindWindow { get; } + public ReactiveCommand ExportCommand { get; } + public Interaction ShowExportWindow { get; } private ViewModelBase _sideContent; private Coin? _selectedCoin; @@ -67,12 +68,29 @@ public class MainWindowViewModel : ViewModelBase { DeleteCommand = ReactiveCommand.CreateFromTask(async () => { var deleteViewModel = new DeleteWindowViewModel(); var result = await ShowDeleteWindow.Handle(deleteViewModel); - if (result && SelectedCoin != null) { + if (result && SelectedCoin is not null) { ConnectedDatabase.DeleteCoin(SelectedCoin); CoinCollection.Remove(SelectedCoin); // possible null deref - ignored due to button being disabled. } }, deleteEnabled); + ShowExportWindow = new Interaction(); + ExportCommand = ReactiveCommand.CreateFromTask(async () => { + var stream = await ShowExportWindow.Handle(Unit.Default); + var writer = new StreamWriter(stream); + try { + await writer.WriteAsync(ConnectedDatabase.CollectionToCSV("CollectionTable")); + await writer.FlushAsync(); + } + catch (IOException e) { + // Something is wrong with the file after it's been created. + Console.WriteLine(e.Message); + } + + writer.Close(); + stream.Close(); + }); + // Set up the ability to open the find window. ShowFindWindow = new Interaction(); var findEnabled = this.WhenAnyValue(x => x.CoinCollection.Count, @@ -84,7 +102,7 @@ public class MainWindowViewModel : ViewModelBase { // Perhaps a secondary viewmodel? return new Coin(); }, findEnabled); - + // Subscribe to SidebarContent.OkCommand, which is an IObservable<(int, string, int)> // This is the same as the above, but with a different syntax. newViewModel.OkCommand diff --git a/PcgsInvUi/Views/MainWindow.axaml b/PcgsInvUi/Views/MainWindow.axaml index d8600da..94f4331 100644 --- a/PcgsInvUi/Views/MainWindow.axaml +++ b/PcgsInvUi/Views/MainWindow.axaml @@ -65,16 +65,16 @@ DockPanel.Dock="Left">