Skip to content

Commit 84f324a

Browse files
committed
Export to XLSX for macOS. Close #2
1 parent 987a466 commit 84f324a

9 files changed

+173
-13
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ The application will look for these files at the following locations (other file
7575
- Directory of the executable file (.exe) for Windows or (.app) for macOS
7676
- `$HOME/.switch` e.g. C:\\Users\\_yourname_\\.switch for Windows, /Users/_yourname_/.switch for macOS or /home/_yourname_/.switch for Linux
7777

78+
`Export` menu supports exporting current list to either `CSV` or `XLSX`. For `CSV` file default delimiter to use is `comma ( , )` and user defined character can be set in `user.settings` by specifying the delimiter character in `CsvSeparator` field
79+
80+
Compressed NCA is not supported, but there is an option to make the application accept `XCZ` and `NSZ` file extension by setting `NszExtension` field `user.settings`. Please note that issues related to these file extensions will not be supported
81+
7882
# macOS
7983
### Open File/Directory
8084
![NX_Game_Info_macOS.png](NX_Game_Info_macOS.png)

cli/NX_Game_Info.csproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
<ApplicationIcon>NX_Game_Info.ico</ApplicationIcon>
3636
</PropertyGroup>
3737
<ItemGroup>
38-
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
39-
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
40-
</Reference>
4138
<Reference Include="PortableSettingsProvider, Version=0.2.3.0, Culture=neutral, processorArchitecture=MSIL">
4239
<HintPath>..\packages\PortableSettingsProvider.0.2.3\lib\net45\PortableSettingsProvider.dll</HintPath>
4340
</Reference>
@@ -53,6 +50,9 @@
5350
<Reference Include="System.Data" />
5451
<Reference Include="System.Net.Http" />
5552
<Reference Include="System.Xml" />
53+
<Reference Include="Newtonsoft.Json">
54+
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
55+
</Reference>
5656
</ItemGroup>
5757
<ItemGroup>
5858
<Compile Include="..\NX_Game_Info\Common.cs" />

cli/Properties/AssemblyInfo.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
//
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
34-
// [assembly: AssemblyVersion("0.7.0.*")]
35-
[assembly: AssemblyVersion("0.7.0.1")]
36-
[assembly: AssemblyFileVersion("0.7.0.1")]
34+
// [assembly: AssemblyVersion("0.7.1.*")]
35+
[assembly: AssemblyVersion("0.7.1.0")]
36+
[assembly: AssemblyFileVersion("0.7.1.0")]

cli/packages.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net461" />
3+
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net471" />
44
<package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net471" />
55
</packages>

macOS/MainMenu.xib

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
2+
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
33
<dependencies>
44
<deployment identifier="macosx"/>
5-
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
66
</dependencies>
77
<objects>
88
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -87,6 +87,11 @@
8787
<modifierMask key="keyEquivalentModifierMask"/>
8888
<menu key="submenu" title="Options" id="cPl-OO-7ff">
8989
<items>
90+
<menuItem title="Update Title Keys" keyEquivalent="T" id="Xic-D0-2VE">
91+
<connections>
92+
<action selector="updateTitleKeys:" target="-1" id="7on-KA-6oP"/>
93+
</connections>
94+
</menuItem>
9095
<menuItem title="Update Version List" keyEquivalent="V" id="2ZD-1S-gOF">
9196
<connections>
9297
<action selector="updateVersionList:" target="-1" id="tyf-nr-kco"/>
@@ -106,6 +111,7 @@
106111
<menu key="submenu" title="History" id="h0J-2S-vTz"/>
107112
</menuItem>
108113
</items>
114+
<point key="canvasLocation" x="139" y="154"/>
109115
</menu>
110116
</objects>
111117
</document>

macOS/MainWindowController.cs

+141-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using AppKit;
88
using Bluegrams.Application;
99
using LibHac;
10+
using OfficeOpenXml;
1011
using FsTitle = LibHac.Title;
1112
using Title = NX_Game_Info.Common.Title;
1213
using ArrayOfTitle = NX_Game_Info.Common.ArrayOfTitle;
@@ -302,7 +303,7 @@ public void OpenSDCard(NSMenuItem menuItem)
302303
public void Export(NSMenuItem menuItem)
303304
{
304305
NSSavePanel savePanel = NSSavePanel.SavePanel;
305-
savePanel.AllowedFileTypes = new string[] { "csv" };
306+
savePanel.AllowedFileTypes = new string[] { "csv", "xlsx" };
306307
savePanel.Title = "Export Titles";
307308

308309
Process.log?.WriteLine("\nExport Titles");
@@ -385,6 +386,134 @@ public void Export(NSMenuItem menuItem)
385386
alert.RunModal();
386387
}
387388
}
389+
else if (filename.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase))
390+
{
391+
using (ExcelPackage excel = new ExcelPackage())
392+
{
393+
Window.BeginSheet(sheet, ProgressComplete);
394+
userCancelled = false;
395+
396+
ExcelWorksheet worksheet = excel.Workbook.Worksheets.Add(Common.History.Default.Titles.LastOrDefault().description ?? NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleExecutable").ToString());
397+
398+
worksheet.Cells[1, 1, 1, Title.Properties.Count()].LoadFromArrays(new List<string[]> { Title.Properties });
399+
worksheet.Cells["1:1"].Style.Font.Bold = true;
400+
worksheet.Cells["1:1"].Style.Font.Color.SetColor(NSColor.White);
401+
worksheet.Cells["1:1"].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
402+
worksheet.Cells["1:1"].Style.Fill.BackgroundColor.SetColor(NSColor.Blue.ShadowWithLevel((nfloat)0.6));
403+
404+
uint index = 0, count = (uint)titles.Count;
405+
406+
foreach (var title in titles)
407+
{
408+
if (userCancelled)
409+
{
410+
userCancelled = false;
411+
break;
412+
}
413+
414+
message.StringValue = title.titleName ?? "";
415+
progress.DoubleValue = 100f * index++ / count;
416+
417+
var data = new List<string[]>
418+
{
419+
new string[] {
420+
title.titleID,
421+
title.baseTitleID,
422+
title.titleName,
423+
title.displayVersion,
424+
title.versionString,
425+
title.latestVersionString,
426+
title.systemUpdateString,
427+
title.systemVersionString,
428+
title.applicationVersionString,
429+
title.masterkeyString,
430+
title.titleKey,
431+
title.publisher,
432+
title.languagesString,
433+
title.filename,
434+
title.filesizeString,
435+
title.typeString,
436+
title.distribution.ToString(),
437+
title.structureString,
438+
title.signatureString,
439+
title.permissionString,
440+
title.error,
441+
}
442+
};
443+
444+
worksheet.Cells[(int)index + 1, 1].LoadFromArrays(data);
445+
446+
string titleID = title.type == TitleType.AddOnContent ? title.titleID : title.baseTitleID ?? "";
447+
448+
Process.latestVersions.TryGetValue(titleID, out uint latestVersion);
449+
Process.versionList.TryGetValue(titleID, out uint version);
450+
Process.titleVersions.TryGetValue(titleID, out uint titleVersion);
451+
452+
if (latestVersion < version || latestVersion < titleVersion)
453+
{
454+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
455+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Fill.BackgroundColor.SetColor(title.signature != true ? NSColor.Orange.ColorWithAlphaComponent((nfloat)0.1) : NSColor.Yellow.ColorWithAlphaComponent((nfloat)0.1));
456+
}
457+
else if (title.signature != true)
458+
{
459+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
460+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Fill.BackgroundColor.SetColor(NSColor.Gray.ColorWithAlphaComponent((nfloat)0.1));
461+
}
462+
463+
if (title.permission == Title.Permission.Dangerous)
464+
{
465+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Font.Color.SetColor(NSColor.Red);
466+
}
467+
else if (title.permission == Title.Permission.Unsafe)
468+
{
469+
worksheet.Cells[(int)index + 1, 1, (int)index + 1, Title.Properties.Count()].Style.Font.Color.SetColor(NSColor.Purple);
470+
}
471+
}
472+
473+
ExcelRange range = worksheet.Cells[1, 1, (int)count + 1, Title.Properties.Count()];
474+
range.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
475+
range.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
476+
range.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
477+
range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
478+
479+
worksheet.Column(1).Width = 18;
480+
worksheet.Column(2).Width = 18;
481+
worksheet.Column(3).AutoFit();
482+
worksheet.Column(3).Width = Math.Max(worksheet.Column(3).Width, 30);
483+
worksheet.Column(4).Width = 16;
484+
worksheet.Column(5).Width = 16;
485+
worksheet.Column(6).Width = 16;
486+
worksheet.Column(7).Width = 16;
487+
worksheet.Column(8).Width = 16;
488+
worksheet.Column(9).Width = 16;
489+
worksheet.Column(10).Width = 16;
490+
worksheet.Column(11).AutoFit();
491+
worksheet.Column(11).Width = Math.Max(worksheet.Column(11).Width, 36);
492+
worksheet.Column(12).AutoFit();
493+
worksheet.Column(12).Width = Math.Max(worksheet.Column(12).Width, 30);
494+
worksheet.Column(13).Width = 18;
495+
worksheet.Column(14).AutoFit();
496+
worksheet.Column(14).Width = Math.Max(worksheet.Column(14).Width, 54);
497+
worksheet.Column(15).Width = 10;
498+
worksheet.Column(16).Width = 10;
499+
worksheet.Column(17).Width = 12;
500+
worksheet.Column(18).Width = 12;
501+
worksheet.Column(19).Width = 10;
502+
worksheet.Column(20).Width = 10;
503+
worksheet.Column(21).Width = 40;
504+
505+
excel.SaveAs(new FileInfo(filename));
506+
507+
Window.EndSheet(sheet);
508+
509+
var alert = new NSAlert()
510+
{
511+
InformativeText = String.Format("{0} of {1} titles exported", index, titles.Count),
512+
MessageText = NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleExecutable").ToString(),
513+
};
514+
alert.RunModal();
515+
}
516+
}
388517
else
389518
{
390519
var alert = new NSAlert()
@@ -441,7 +570,7 @@ public void UpdateVersionList(NSMenuItem menuItem)
441570
Window.BeginSheet(sheet, ProgressComplete);
442571

443572
title.StringValue = "";
444-
message.StringValue = String.Format("Downloading from {0}", Common.TAGAYA_VERSIONLIST);
573+
message.StringValue = String.Format("Downloading from {0}", Common.HAC_VERSIONLIST_URI);
445574
progress.DoubleValue = 0;
446575

447576
if (Process.updateVersionList())
@@ -1079,4 +1208,14 @@ public override NSView GetViewForItem(NSTableView tableView, NSTableColumn table
10791208
return textField;
10801209
}
10811210
}
1211+
1212+
public static class ExcelColorExtension
1213+
{
1214+
public static void SetColor(this OfficeOpenXml.Style.ExcelColor excelColor, NSColor color)
1215+
{
1216+
NSColor rgb = color.UsingColorSpace(NSColorSpace.DeviceRGB);
1217+
nfloat alpha = rgb.AlphaComponent;
1218+
excelColor.SetColor(255, (int)((1 + alpha * (rgb.RedComponent - 1)) * 255), (int)((1 + alpha * (rgb.GreenComponent - 1)) * 255), (int)((1 + alpha * (rgb.BlueComponent - 1)) * 255));
1219+
}
1220+
}
10821221
}

macOS/MainWindowController.designer.cs

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

macOS/NX_Game_Info.csproj

+8-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
<Reference Include="mscorlib" />
5858
<Reference Include="System.Numerics" />
5959
<Reference Include="Newtonsoft.Json">
60-
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
60+
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
6161
</Reference>
6262
<Reference Include="System.Xml" />
6363
<Reference Include="System.Xml.Linq" />
@@ -95,6 +95,13 @@
9595
</Reference>
9696
<Reference Include="System.Net.Http" />
9797
<Reference Include="System.Net.Http.WebRequest" />
98+
<Reference Include="EPPlus">
99+
<HintPath>..\packages\EPPlus.4.5.3.2\lib\net40\EPPlus.dll</HintPath>
100+
</Reference>
101+
<Reference Include="PresentationCore" />
102+
<Reference Include="System.Data" />
103+
<Reference Include="System.Drawing" />
104+
<Reference Include="System.Security" />
98105
</ItemGroup>
99106
<ItemGroup>
100107
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json" />

macOS/packages.config

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3+
<package id="EPPlus" version="4.5.3.2" targetFramework="net471" />
34
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net471" />
45
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net471" />
56
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net471" />
6-
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net471" />
7+
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net471" />
78
<package id="PortableSettingsProvider" version="0.2.2" targetFramework="net471" />
89
<package id="System.IO" version="4.3.0" targetFramework="net471" />
910
<package id="System.Runtime" version="4.3.0" targetFramework="net471" />

0 commit comments

Comments
 (0)