Implemented export to CSV functionality.
This commit is contained in:
1 parent
a478d4ebb0
commit
ddbc745200
4 files changed
+97
-8
No files matched your search
@@ -122,6 +122,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.
|
||||
SQLiteCommand cmd = Connection.CreateCommand();
|
||||
|
||||
@@ -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<DeleteWindowViewModel, Boolean> ShowDeleteWindow { get; }
|
||||
public ReactiveCommand<Unit, Coin> FindCommand { get; }
|
||||
public Interaction<FindWindowViewModel, int> ShowFindWindow { get; }
|
||||
public ReactiveCommand<Unit, Unit> ExportCommand { get; }
|
||||
public Interaction<Unit, Stream> 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<Unit, Stream>();
|
||||
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<FindWindowViewModel, int>();
|
||||
var findEnabled = this.WhenAnyValue(x => x.CoinCollection.Count,
|
||||
|
||||
@@ -65,16 +65,16 @@
|
||||
DockPanel.Dock="Left">
|
||||
<Button Grid.Column="0" Margin="5" Width="100" HorizontalContentAlignment="Center" Content="Delete"
|
||||
Command="{Binding DeleteCommand}" />
|
||||
<Button Grid.Column="1" Margin="5" Width="100" HorizontalContentAlignment="Center"
|
||||
Content="Find..."
|
||||
Command="{Binding FindCommand}" />
|
||||
<!-- <Button Grid.Column="1" Margin="5" Width="100" HorizontalContentAlignment="Center" -->
|
||||
<!-- Content="Find..." -->
|
||||
<!-- Command="{Binding FindCommand}" /> -->
|
||||
</Grid>
|
||||
<Grid HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="5" ColumnDefinitions="Auto, Auto"
|
||||
DockPanel.Dock="Right">
|
||||
<Label Grid.Column="0" Margin="5" VerticalAlignment="Center"
|
||||
Content="{Binding TotalValue, StringFormat='Total Value: ${0:0.00}'}" />
|
||||
<Button Grid.Column="1" Margin="5" Width="150" HorizontalContentAlignment="Center"
|
||||
Content="Export to CSV..." />
|
||||
Content="Export to CSV..." Command="{Binding ExportCommand}" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.ReactiveUI;
|
||||
using PcgsInvUi.ViewModels;
|
||||
using ReactiveUI;
|
||||
@@ -10,7 +13,8 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel> {
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
this.WhenActivated(d => d(ViewModel!.ShowDeleteWindow.RegisterHandler(ShowDeleteWindowAsync)));
|
||||
this.WhenActivated(d => d(ViewModel!.ShowFindWindow.RegisterHandler(ShowFindWindowAsync)));
|
||||
this.WhenActivated(d => d(ViewModel!.ShowExportWindow.RegisterHandler(ShowFilePickerAsync)));
|
||||
// this.WhenActivated(d => d(ViewModel!.ShowFindWindow.RegisterHandler(ShowFindWindowAsync)));
|
||||
}
|
||||
|
||||
public async Task ShowDeleteWindowAsync(InteractionContext<DeleteWindowViewModel, Boolean> interaction) {
|
||||
@@ -28,4 +32,22 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel> {
|
||||
var result = await window.ShowDialog<int>(this);
|
||||
interaction.SetOutput(result);
|
||||
}
|
||||
|
||||
public async Task ShowFilePickerAsync(InteractionContext<Unit, Stream> interationContext) {
|
||||
var topLevel = GetTopLevel(this);
|
||||
var file = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions {
|
||||
Title = "Save CSV...",
|
||||
DefaultExtension = ".csv",
|
||||
ShowOverwritePrompt = true,
|
||||
SuggestedFileName = "coins.csv",
|
||||
SuggestedStartLocation = await StorageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents)
|
||||
});
|
||||
|
||||
Stream stream;
|
||||
|
||||
if (file is not null) {
|
||||
stream = await file.OpenWriteAsync();
|
||||
interationContext.SetOutput(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user