diff --git a/Makefile b/Makefile
index d53b59fb..44a856a8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,16 @@
SHELL := /bin/bash
-.PHONY: credits publish-alpha all
+.PHONY: credits publish all
help:
# Target publish-alpha: Pushes the current alpha version to the server using the latest tag
# Also pushes the branch and tags to the remote repository
-credits: XLToolbox/html/credits.html
+credits: XLToolbox/Resources/html/credits.html
-XLToolbox/html/credits.html: ../web/content/about.html.haml
- sed -e '1,//d; /vim:/d; s/^\( \)\{3\}//' ../web/content/about.html.haml | perl -0777 -pe 's/\[([^]]+)\]\([^)]+\)/\1/msg' | pandoc -H XLToolbox/html/style.html > XLToolbox/html/credits.html
+XLToolbox/Resources/html/credits.html: ../web/content/about.haml
+ sed -e '1,//d; /vim:/d; s/^\( \)\{4\}//' ../web/content/about.haml | perl -0777 -pe 's/\[([^]]+)\]\([^)]+\)/\1/msg' | pandoc -H XLToolbox/Resources/html/style.html > XLToolbox/Resources/html/credits.html
-GITTAG=$(shell git describe master)
-VERSION=$(GITTAG:v%=%)
-publish-beta:
- scp publish/release/XLToolbox-$(VERSION).exe bovender@frs.sourceforge.net:/home/frs/project/xltoolbox/beta/
+publish:
git push
git push --tags
+ publish/create-release.rb
diff --git a/Tests/Csv/CsvFileTest.cs b/Tests/Csv/CsvFileTest.cs
index 3dd2ecd5..38a38139 100755
--- a/Tests/Csv/CsvFileTest.cs
+++ b/Tests/Csv/CsvFileTest.cs
@@ -39,20 +39,13 @@ public void ExportSimpleCsv()
// For testing we 'hide' a pipe symbol in the field.
ws.Cells[4, 5] = "wor|d";
ws.Cells[4, 6] = 88.5;
- CsvFile csv = new CsvFile();
+ CsvExporter model = new CsvExporter();
string fn = System.IO.Path.GetTempFileName();
- csv.FileName = fn;
- csv.FieldSeparator = "|";
+ model.FileName = fn;
+ model.FieldSeparator = "|";
// Use a funky decimal separator
- csv.DecimalSeparator = "~";
- csv.Export();
- Task t = new Task(() =>
- {
- while (csv.IsProcessing) { }
- });
- t.Start();
- t.Wait(5000);
- Assert.IsFalse(csv.IsProcessing, "Exporter is still processing!");
+ model.DecimalSeparator = "~";
+ model.Execute();
string contents = System.IO.File.ReadAllText(fn);
string expected = String.Format(
"hello|13{0}\"wor|d\"|88~5{0}",
@@ -67,24 +60,25 @@ public void ExportLargeCsv()
Worksheet ws = Instance.Default.ActiveWorkbook.Worksheets.Add();
ws.Cells[1, 1] = "hello";
ws.Cells[1000, 16384]= "world";
- CsvFile csv = new CsvFile();
+ CsvExporter model = new CsvExporter();
+ CsvExportViewModel vm = new CsvExportViewModel(model);
string fn = System.IO.Path.GetTempFileName();
- csv.FileName = fn;
+ vm.FileName = fn;
bool progressCompletedRaised = false;
- csv.ProcessSucceeded += (sender, args) =>
+ vm.ProcessFinishedMessage.Sent += (sender, args) =>
{
progressCompletedRaised = true;
};
- csv.Export();
+ vm.StartProcess();
Task t = new Task(() =>
{
- while (csv.IsProcessing) { }
+ while (model.IsProcessing) { }
});
t.Start();
t.Wait(15000);
- if (csv.IsProcessing)
+ if (vm.IsProcessing)
{
- csv.CancelExport();
+ vm.CancelProcess();
Assert.Inconclusive("CSV export took too long, did not finish.");
// Do not delete the file, leave it for inspection
}
@@ -105,12 +99,13 @@ public void CsvExportPerformance()
Worksheet ws = Instance.Default.ActiveWorkbook.Worksheets.Add();
ws.Cells[1, 1] = "hello";
ws.Cells[200, 5] = "world";
- CsvFile csv = new CsvFile();
+ CsvExporter model = new CsvExporter();
+ CsvExportViewModel vm = new CsvExportViewModel(model);
string fn = System.IO.Path.GetTempFileName();
- csv.FileName = fn;
+ model.FileName = fn;
bool running = true;
long start = 0;
- csv.ProcessSucceeded += (sender, args) =>
+ vm.ProcessFinishedMessage.Sent += (sender, args) =>
{
Console.WriteLine(method + ": *** Export completed ***");
long stop = DateTime.Now.Ticks;
@@ -130,7 +125,8 @@ public void CsvExportPerformance()
);
waitTask.Start();
start = DateTime.Now.Ticks;
- csv.Export(ws.UsedRange);
+ model.Range = ws.UsedRange;
+ vm.StartProcess();
waitTask.Wait(-1);
}
diff --git a/Tests/Excel/WorkbookViewModelTest.cs b/Tests/Excel/WorkbookViewModelTest.cs
index 13083787..04146b54 100755
--- a/Tests/Excel/WorkbookViewModelTest.cs
+++ b/Tests/Excel/WorkbookViewModelTest.cs
@@ -25,12 +25,19 @@
namespace XLToolbox.Test.Excel
{
+
///
/// Unit tests for the XLToolbox.Core.Excel namespace.
///
[TestFixture]
class WorkbookViewModelTest
{
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ Instance.Default.Dispose();
+ }
+
[Test]
public void WorkbookViewModelProperties()
{
@@ -60,6 +67,7 @@ public void MoveSheetsUp()
// With no sheets selected, the move-up command should
// be disabled.
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.IsFalse(wvm.MoveSheetUp.CanExecute(null),
"Move command is enabled, should be disabled with no sheets selected.");
@@ -91,6 +99,7 @@ public void MoveSheetsDown()
// With no sheets selected, the move-down command should
// be disabled.
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.IsFalse(wvm.MoveSheetDown.CanExecute(null),
"Move-down command is enabled, should be disabled with no sheets selected.");
@@ -122,10 +131,12 @@ public void MoveFirstSheetDown()
// With no sheets selected, the move-down command should
// be disabled.
+ wb.Sheets[wb.Sheets.Count].Activate();
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.IsFalse(wvm.MoveSheetDown.CanExecute(null),
"Move-down command is enabled, should be disabled with no sheets selected.");
- svm.IsSelected = true;
+ wb.Sheets[1].Activate();
Assert.IsTrue(wvm.MoveSheetDown.CanExecute(null),
"Move-down command is disabled, should be enabled with one sheet selected.");
@@ -140,15 +151,16 @@ public void MoveSheetsToTop()
{
Workbook wb = Instance.Default.CreateWorkbook(8);
WorkbookViewModel wvm = new WorkbookViewModel(wb);
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
// Without sheets selected, the Move-to-top command should be disabled
Assert.IsFalse(wvm.MoveSheetsToTop.CanExecute(null),
"The Move-to-top command should be disabled without selected sheets.");
- // Select the fourth and sixth sheets and remember their names
- SheetViewModel svm4 = wvm.Sheets[3];
- svm4.IsSelected = true;
- string sheetName4 = svm4.DisplayString;
+ // // Select the fourth and sixth sheets and remember their names
+ // SheetViewModel svm4 = wvm.Sheets[3];
+ // svm4.IsSelected = true;
+ // string sheetName4 = svm4.DisplayString;
SheetViewModel svm6 = wvm.Sheets[5];
svm6.IsSelected = true;
@@ -168,9 +180,9 @@ public void MoveSheetsToTop()
// Verify that the display strings of the view models correspond to
// the names of the worksheets in the workbook, to make sure that
// the worksheets have indeed been rearranged as well.
- Assert.AreEqual(sheetName4, wb.Sheets[1].Name,
- "Moving the sheets to top was not performed on the actual workbook");
- Assert.AreEqual(sheetName6, wb.Sheets[2].Name,
+ // Assert.AreEqual(sheetName4, wb.Sheets[1].Name,
+ // "Moving the sheets to top was not performed on the actual workbook");
+ Assert.AreEqual(sheetName6, wb.Sheets[1].Name,
"Moving the sheets to top was not performed for all sheets on the actual workbook");
}
@@ -181,13 +193,14 @@ public void MoveSheetsToBottom()
WorkbookViewModel wvm = new WorkbookViewModel(wb);
// Without sheets selected, the Move-to-bottom command should be disabled
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.IsFalse(wvm.MoveSheetsToBottom.CanExecute(null),
"The Move-to-bottom command should be disabled without selected sheets.");
// Select the fourth and sixth sheets and remember their names
- SheetViewModel svm2 = wvm.Sheets[1];
- svm2.IsSelected = true;
- string sheetName2 = svm2.DisplayString;
+ // SheetViewModel svm2 = wvm.Sheets[1];
+ // svm2.IsSelected = true;
+ // string sheetName2 = svm2.DisplayString;
SheetViewModel svm4 = wvm.Sheets[3];
svm4.IsSelected = true;
@@ -207,8 +220,8 @@ public void MoveSheetsToBottom()
// Verify that the display strings of the view models correspond to
// the names of the worksheets in the workbook, to make sure that
// the worksheets have indeed been rearranged as well.
- Assert.AreEqual(sheetName2, wb.Sheets[wb.Sheets.Count-1].Name,
- "Moving the sheets to bottom was not performed on the actual workbook");
+ // Assert.AreEqual(sheetName2, wb.Sheets[wb.Sheets.Count-1].Name,
+ // "Moving the sheets to bottom was not performed on the actual workbook");
Assert.AreEqual(sheetName4, wb.Sheets[wb.Sheets.Count].Name,
"Moving the sheets to bottom was not performed for all sheets on the actual workbook");
}
@@ -219,10 +232,11 @@ public void DeleteSheets()
Workbook wb = Instance.Default.CreateWorkbook(8);
int oldCount = wb.Sheets.Count;
WorkbookViewModel wvm = new WorkbookViewModel(wb);
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.IsFalse(wvm.DeleteSheets.CanExecute(null),
"Delete sheets command should be disabled with no sheets selected.");
wvm.Sheets[2].IsSelected = true;
- wvm.Sheets[4].IsSelected = true;
+ // wvm.Sheets[4].IsSelected = true;
string sheetName3 = wvm.Sheets[2].DisplayString;
string sheetName5 = wvm.Sheets[4].DisplayString;
int numSelected = wvm.NumSelectedSheets;
@@ -256,12 +270,12 @@ public void DeleteSheets()
},
String.Format("Sheet {0} (sheetName3) should have been deleted but is still there.", sheetName3)
);
- Assert.Throws(typeof(System.Runtime.InteropServices.COMException), () =>
- {
- obj = wb.Sheets[sheetName5];
- },
- String.Format("Sheet {0} (sheetName5) should have been deleted but is still there.", sheetName5)
- );
+ // Assert.Throws(typeof(System.Runtime.InteropServices.COMException), () =>
+ // {
+ // obj = wb.Sheets[sheetName5];
+ // },
+ // String.Format("Sheet {0} (sheetName5) should have been deleted but is still there.", sheetName5)
+ // );
}
[Test]
@@ -283,6 +297,7 @@ public void RenameSheet()
string oldName = wvm.Sheets[0].DisplayString;
string newName = "valid new name";
bool messageSent = false;
+ wvm.Sheets.First(sheet => sheet.IsSelected).IsSelected = false;
Assert.False(wvm.RenameSheet.CanExecute(null),
"Rename sheet command should be disabled with no sheet selected.");
wvm.Sheets[0].IsSelected = true;
diff --git a/Tests/Export/ExporterTest.cs b/Tests/Export/ExporterTest.cs
index 3b506c2e..7c84c561 100755
--- a/Tests/Export/ExporterTest.cs
+++ b/Tests/Export/ExporterTest.cs
@@ -17,27 +17,36 @@
*/
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Text;
-using System.IO;
-using NUnit.Framework;
+using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Office.Interop.Excel;
-using XLToolbox.Export;
-using XLToolbox.Excel.ViewModels;
+using NUnit.Framework;
using Bovender.Unmanaged;
+using XLToolbox.Excel.ViewModels;
+using XLToolbox.Export;
using XLToolbox.Export.Models;
-using System.Threading.Tasks;
+using XLToolbox.Export.ViewModels;
namespace XLToolbox.Test.Export
{
[TestFixture]
class ExporterTest
{
- [SetUp]
+ [TestFixtureSetUp]
public void SetUp()
{
// Force starting Excel
Instance i = Instance.Default;
+ SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
+ }
+
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ Instance.Default.Dispose();
}
[Test]
@@ -68,8 +77,8 @@ public void ExportChartObject(FileType fileType, int dpi, ColorSpace colorSpace)
settings.Width = 160;
settings.Height = 40;
File.Delete(settings.FileName);
- Exporter exporter = new Exporter();
- exporter.ExportSelection(settings);
+ Exporter exporter = new Exporter(settings);
+ exporter.Execute();
Assert.IsTrue(File.Exists(settings.FileName));
}
@@ -85,13 +94,12 @@ public void ExportChartSheet()
settings.FileName = Path.GetFileNameWithoutExtension(Path.GetTempFileName())
+ preset.FileType.ToFileNameExtension();
File.Delete(settings.FileName);
- Exporter exporter = new Exporter();
- exporter.ExportSelectionQuick(settings);
+ Exporter exporter = new Exporter(settings, true);
+ exporter.Execute();
Assert.IsTrue(File.Exists(settings.FileName), "Output file was not created.");
}
[Test]
- [RequiresSTA]
[TestCase(BatchExportScope.ActiveSheet, BatchExportObjects.Charts, BatchExportLayout.SingleItems, 1)]
[TestCase(BatchExportScope.ActiveWorkbook, BatchExportObjects.Charts, BatchExportLayout.SingleItems, 7)]
[TestCase(BatchExportScope.ActiveWorkbook, BatchExportObjects.Charts, BatchExportLayout.SheetLayout, 4)]
@@ -120,17 +128,16 @@ public void BatchExport(
settings.Layout = layout;
settings.Objects = objects;
settings.Scope = scope;
- Exporter exporter = new Exporter();
+ BatchExporter exporter = new BatchExporter(settings);
+ BatchExportSettingsViewModel vm = new BatchExportSettingsViewModel(exporter);
bool finished = false;
- exporter.ProcessSucceeded += (sender, args) => { finished = true; };
- exporter.ExportBatchAsync(settings);
- Task checkFinishedTask = new Task(() =>
- {
- while (finished == false) ;
- });
- checkFinishedTask.Start();
- checkFinishedTask.Wait(10000);
- Assert.IsTrue(finished, "Export progress did not finish, timeout reached.");
+ bool abort = false;
+ vm.ProcessFinishedMessage.Sent += (sender, args) => { finished = true; };
+ vm.StartProcess();
+ Timer t = new Timer((obj) => abort = true, null, 8000, Timeout.Infinite);
+ while (!finished && !abort) ;
+ t.Dispose();
+ Assert.IsFalse(abort, "Export progress did not finish, timeout reached.");
Assert.AreEqual(expectedNumberOfFiles,
Directory.GetFiles(settings.Path).Length);
Directory.Delete(settings.Path, true);
diff --git a/Tests/Properties/AssemblyInfo.cs b/Tests/Properties/AssemblyInfo.cs
index ce461fad..e2402777 100755
--- a/Tests/Properties/AssemblyInfo.cs
+++ b/Tests/Properties/AssemblyInfo.cs
@@ -49,5 +49,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("7.0.0.26")]
-[assembly: AssemblyFileVersion("7.0.0.26")]
+[assembly: AssemblyVersion("7.0.0.27")]
+[assembly: AssemblyFileVersion("7.0.0.27")]
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 2b619e42..d0a3dc06 100755
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -51,15 +51,15 @@
-
+ False
- ..\packages\Bovender.0.10.0.0\lib\net40\Bovender.dll
+ ..\packages\Bovender.0.11.0.0\lib\net40\Bovender.dll
-
+ False
- ..\packages\Bovender.0.10.0.0\lib\net40\Bovender.dll
+ ..\packages\Bovender.0.11.0.0\lib\net40\Bovender.dll
diff --git a/Tests/packages.config b/Tests/packages.config
index 00f3b376..4fa43502 100755
--- a/Tests/packages.config
+++ b/Tests/packages.config
@@ -19,7 +19,7 @@
limitations under the License.
-->
-
+
diff --git a/VERSION b/VERSION
index 4e4bfa10..081ece0a 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-7.0.0-beta.7
-7.0.0.26
+7.0.0
+7.0.0.27
diff --git a/XLToolbox.zreproj b/XLToolbox.zreproj
new file mode 100755
index 00000000..ebba91e6
--- /dev/null
+++ b/XLToolbox.zreproj
@@ -0,0 +1,62 @@
+
+
+
+ ####
+ False
+ 0
+ 118
+ True
+ False
+ <XtraSerializer version="1.0" application="View">
+ <property name="#LayoutVersion" />
+ <property name="ActiveFilterString" />
+</XtraSerializer>
+ <XtraSerializer version="1.0" application="View">
+ <property name="#LayoutVersion" />
+ <property name="SortInfo">~Xtra#Base64AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFHcmlkLnYxNi4xLCBWZXJzaW9uPTE2LjEuNC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAAADhEZXZFeHByZXNzLlh0cmFHcmlkLkNvbHVtbnMuR3JpZENvbHVtblNvcnRJbmZvQ29sbGVjdGlvbgQAAAAKZ3JvdXBDb3VudAVjbG9uZQ9jbG9uZUdyb3VwQ291bnQTQ29sbGVjdGlvbkJhc2UrbGlzdAADAAMIsgFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW0RldkV4cHJlc3MuWHRyYUdyaWQuQ29sdW1ucy5HcmlkQ29sdW1uU29ydEluZm8sIERldkV4cHJlc3MuWHRyYUdyaWQudjE2LjEsIFZlcnNpb249MTYuMS40LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YV1dCBxTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0AgAAAAAAAAAJAwAAAAAAAAAJBAAAAAQDAAAAsgFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW0RldkV4cHJlc3MuWHRyYUdyaWQuQ29sdW1ucy5HcmlkQ29sdW1uU29ydEluZm8sIERldkV4cHJlc3MuWHRyYUdyaWQudjE2LjEsIFZlcnNpb249MTYuMS40LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YV1dAwAAAAZfaXRlbXMFX3NpemUIX3ZlcnNpb24EAAAwRGV2RXhwcmVzcy5YdHJhR3JpZC5Db2x1bW5zLkdyaWRDb2x1bW5Tb3J0SW5mb1tdAgAAAAgICQUAAAAAAAAAAAAAAAQEAAAAHFN5c3RlbS5Db2xsZWN0aW9ucy5BcnJheUxpc3QDAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgUAAAgICQYAAAABAAAABAAAAAcFAAAAAAEAAAAAAAAABC5EZXZFeHByZXNzLlh0cmFHcmlkLkNvbHVtbnMuR3JpZENvbHVtblNvcnRJbmZvAgAAABAGAAAABAAAAAkHAAAADQMMCAAAABlEZXZFeHByZXNzLlh0cmFHcmlkLnYxNi4xBQcAAAAuRGV2RXhwcmVzcy5YdHJhR3JpZC5Db2x1bW5zLkdyaWRDb2x1bW5Tb3J0SW5mbwIAAAAJU29ydE9yZGVyCkNvbHVtbk5hbWUAAQgIAAAAAQAAAAYJAAAABWNvbGRlCw==</property>
+</XtraSerializer>
+ ####
+ False
+ -1
+
+
+ <?xml version='1.0' encoding='utf-8'?><items><item type="2" checksum="2064426735" /></items>
+ X:\Code\xltoolbox\NG\XLToolboxForExcel
+
+
+ X:\Code\xltoolbox\NG\XLToolbox\Strings.resx;X:\Code\xltoolbox\NG\XLToolbox\Strings.de.resx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XLToolbox/Csv/CsvExportViewModel.cs b/XLToolbox/Csv/CsvExportViewModel.cs
index 0a428a35..4c3a43d9 100755
--- a/XLToolbox/Csv/CsvExportViewModel.cs
+++ b/XLToolbox/Csv/CsvExportViewModel.cs
@@ -26,16 +26,17 @@
using Microsoft.Office.Interop.Excel;
using System.Threading.Tasks;
using System.Threading;
+using System.Diagnostics;
namespace XLToolbox.Csv
{
- class CsvExportViewModel : ProcessViewModelBase
+ public class CsvExportViewModel : ProcessViewModelBase
{
#region Factory
public static CsvExportViewModel FromLastUsed()
{
- return new CsvExportViewModel(CsvFile.LastExport());
+ return new CsvExportViewModel(CsvExporter.LastExport());
}
#endregion
@@ -44,40 +45,40 @@ public static CsvExportViewModel FromLastUsed()
public string FileName
{
- get { return _csvFile.FileName; }
+ get { return CsvExporter.FileName; }
set
{
- _csvFile.FileName = value;
+ CsvExporter.FileName = value;
OnPropertyChanged("FileName");
}
}
public string FieldSeparator
{
- get { return _csvFile.FieldSeparator; }
+ get { return CsvExporter.FieldSeparator; }
set
{
- _csvFile.FieldSeparator = value;
+ CsvExporter.FieldSeparator = value;
OnPropertyChanged("FieldSeparator");
}
}
public string DecimalSeparator
{
- get { return _csvFile.DecimalSeparator; }
+ get { return CsvExporter.DecimalSeparator; }
set
{
- _csvFile.DecimalSeparator = value;
+ CsvExporter.DecimalSeparator = value;
OnPropertyChanged("DecimalSeparator");
}
}
public string ThousandsSeparator
{
- get { return _csvFile.ThousandsSeparator; }
+ get { return CsvExporter.ThousandsSeparator; }
set
{
- _csvFile.ThousandsSeparator = value;
+ CsvExporter.ThousandsSeparator = value;
OnPropertyChanged("ThousandsSeparator");
}
}
@@ -138,24 +139,34 @@ public Message ChooseExportFileNameMessage
#region Constructors
public CsvExportViewModel()
- : this(new CsvFile()) { }
+ : this(new CsvExporter()) { }
- protected CsvExportViewModel(CsvFile model)
- : base()
+ public CsvExportViewModel(CsvExporter model)
+ : base(model)
+ { }
+
+ #endregion
+
+ #region Implementation of ProcessViewModel
+
+ protected override int GetPercentCompleted()
{
- _csvFile = model;
- ProcessModel = _csvFile; // also hooks up events
+ return Convert.ToInt32(100d * CsvExporter.CellsProcessed / CsvExporter.CellsTotal);
}
#endregion
- #region ViewModelBase implementation
+ #region Private properties
- public override object RevealModelObject()
+ private CsvExporter CsvExporter
{
- return _csvFile;
+ [DebuggerStepThrough]
+ get
+ {
+ return ProcessModel as CsvExporter;
+ }
}
-
+
#endregion
#region Private methods
@@ -174,7 +185,7 @@ private void ConfirmChooseFileName(FileNameMessageContent messageContent)
{
if (messageContent.Confirmed)
{
- _csvFile.FileName = messageContent.Value;
+ CsvExporter.FileName = messageContent.Value;
DoExport();
}
}
@@ -185,6 +196,7 @@ private void DoExport()
{
store.Put("csv_path", System.IO.Path.GetDirectoryName(FileName));
};
+ ((CsvExporter)ProcessModel).Range = Range;
StartProcess();
}
@@ -192,42 +204,10 @@ private void DoExport()
#region Private fields
- CsvFile _csvFile;
DelegatingCommand _chooseFileNameCommand;
DelegatingCommand _exportCommand;
Message _chooseExportFileNameMessage;
#endregion
-
- #region Implementation of ProcessViewModel
-
- protected override void CancelProcess()
- {
- _csvFile.CancelExport();
- }
-
- protected override void Execute()
- {
- if (Range != null)
- {
- _csvFile.Export(Range);
- }
- else
- {
- _csvFile.Export();
- }
- }
-
- protected override int GetPercentCompleted()
- {
- return Convert.ToInt32(100d * _csvFile.CellsProcessed / _csvFile.CellsTotal);
- }
-
- protected override bool IsProcessing()
- {
- return _csvFile.IsProcessing;
- }
-
- #endregion
}
}
diff --git a/XLToolbox/Csv/CsvExporter.cs b/XLToolbox/Csv/CsvExporter.cs
new file mode 100755
index 00000000..1b780be3
--- /dev/null
+++ b/XLToolbox/Csv/CsvExporter.cs
@@ -0,0 +1,231 @@
+/* CsvExporter.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using YamlDotNet.Serialization;
+using Microsoft.Office.Interop.Excel;
+using XLToolbox.Excel;
+
+namespace XLToolbox.Csv
+{
+ public class CsvExporter : CsvFileBase
+ {
+ #region Factory
+
+ public static CsvExporter LastExport()
+ {
+ CsvSettings settings = UserSettings.UserSettings.Default.CsvSettings;
+ if (settings == null)
+ {
+ return new CsvExporter();
+ }
+ else
+ {
+ return new CsvExporter(settings);
+ }
+ }
+
+ #endregion
+
+ #region Public properties
+
+ ///
+ /// Gets whether the exporter is currently processing.
+ ///
+ [YamlIgnore]
+ public bool IsProcessing { get; private set; }
+
+ ///
+ /// Gets the number of cells that were already processed
+ /// during export.
+ ///
+ [YamlIgnore]
+ public long CellsProcessed { get; private set; }
+
+ ///
+ /// Gets the total number of cells to export.
+ ///
+ [YamlIgnore]
+ public long CellsTotal { get; private set; }
+
+ [YamlIgnore]
+ public Range Range { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ public CsvExporter()
+ : base()
+ { }
+
+ public CsvExporter(CsvSettings settings)
+ : base(settings)
+ { }
+
+ #endregion
+
+ #region Implementation of ProcessModel
+
+ ///
+ /// Exports the Range to a CSV file, using the file name specified
+ /// in the property.
+ ///
+ /// Range to export.
+ public override bool Execute()
+ {
+ Logger.Info("Export: Exporting CSV: FS='{0}', DS='{1}', TS='{2}'",
+ FieldSeparator, DecimalSeparator, ThousandsSeparator);
+ bool result = false;
+ UserSettings.UserSettings.Default.CsvSettings = Settings;
+ if (Range == null)
+ {
+ Range = UsedRange();
+ }
+ if (Range == null)
+ {
+ throw new InvalidOperationException("Cannot export CSV: No range given, and the used range cannot be determined.");
+ }
+
+ StreamWriter sw = null;
+ try
+ {
+ // StreamWriter buffers the output; using a StringBuilder
+ // doesn't speed up things (tried it)
+ sw = File.CreateText(FileName);
+ CellsTotal = Range.CellsCount();
+ Logger.Info("Number of cells: {0}", CellsTotal);
+ CellsProcessed = 0;
+ string fs = FieldSeparator;
+ if (fs == "\\t") { fs = "\t"; } // Convert "\t" to tab characters
+
+ // Get all values in an array
+ foreach (Range row in Range.Rows)
+ {
+ // object[,] values = range.Value2;
+ object[,] values = row.Value2;
+ if (values != null)
+ {
+ //for (long row = 1; row <= values.GetLength(0); row++)
+ //{
+ for (long col = 1; col <= values.GetLength(1); col++)
+ {
+ CellsProcessed++;
+
+ // If this is not the first field in the line, write a field separator.
+ if (col > 1)
+ {
+ sw.Write(fs);
+ }
+
+ // object value = values[row, col];
+ object value = values[1, col]; // 1-based index!
+ if (value != null)
+ {
+ if (value is string)
+ {
+ string s = value as string;
+ if (s.Contains(fs) || s.Contains("\""))
+ {
+ s = "\"" + s.Replace("\"", "\"\"") + "\"";
+ }
+ sw.Write(s);
+ }
+ else
+ {
+ double d = Convert.ToDouble(value);
+ sw.Write(d.ToString(NumberFormatInfo));
+ }
+ }
+ if (IsCancellationRequested) break;
+ }
+ sw.WriteLine();
+ }
+ if (IsCancellationRequested)
+ {
+ sw.WriteLine(UNFINISHED_EXPORT);
+ sw.WriteLine("Cancelled by user.");
+ Logger.Info("CSV export cancelled by user");
+ break;
+ }
+ // }
+ }
+ sw.Close();
+ }
+ catch (IOException ioException)
+ {
+ IsProcessing = false;
+ throw ioException;
+ }
+ catch (Exception anyException)
+ {
+ IsProcessing = false;
+ if (sw != null)
+ {
+ sw.WriteLine(UNFINISHED_EXPORT);
+ sw.WriteLine(anyException.ToString());
+ sw.Close();
+ }
+ throw anyException;
+ }
+ finally
+ {
+ IsProcessing = false;
+ Logger.Info("CSV export task finished");
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Private helper methods
+
+ private Range UsedRange()
+ {
+ Worksheet worksheet = Excel.ViewModels.Instance.Default.ActiveWorkbook.ActiveSheet as Worksheet;
+ if (worksheet != null)
+ {
+ return worksheet.UsedRange;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ #endregion
+
+ #region Private constant
+
+ const string UNFINISHED_EXPORT = "*** UNFINISHED EXPORT ***";
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/Csv/CsvFile.cs b/XLToolbox/Csv/CsvFile.cs
deleted file mode 100755
index a23366ca..00000000
--- a/XLToolbox/Csv/CsvFile.cs
+++ /dev/null
@@ -1,309 +0,0 @@
-/* CsvFile.cs
- * part of Daniel's XL Toolbox NG
- *
- * Copyright 2014-2016 Daniel Kraus
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.IO;
-using Microsoft.Office.Interop.Excel;
-using System.Globalization;
-using XLToolbox.Excel;
-using System.Threading.Tasks;
-using System.Xml.Serialization;
-
-namespace XLToolbox.Csv
-{
- ///
- /// Provides import/export settings and methods for CSV files.
- ///
- public class CsvFile : Bovender.Mvvm.Models.ProcessModel
- {
- #region Factory
-
- public static CsvFile LastImport()
- {
- CsvFile c = UserSettings.UserSettings.Default.CsvImport;
- if (c == null)
- {
- c = new CsvFile();
- }
- return c;
- }
-
- public static CsvFile LastExport()
- {
- CsvFile c = UserSettings.UserSettings.Default.CsvExport;
- if (c == null)
- {
- c = new CsvFile();
- }
- return c;
- }
-
- #endregion
-
- #region Public properties
-
- public string FileName { get; set; }
-
- public string FieldSeparator { get; set; }
-
- public string DecimalSeparator
- {
- get { return NumberFormatInfo.NumberDecimalSeparator; }
- set { NumberFormatInfo.NumberDecimalSeparator = value; }
- }
-
- public string ThousandsSeparator
- {
- get { return NumberFormatInfo.NumberGroupSeparator; }
- set { NumberFormatInfo.NumberGroupSeparator = value; }
- }
-
- ///
- /// Returns a System.Globalization.NumberFormatInfo object
- /// whose properties are set according to the current
- /// properties (namely, .)
- /// This property is mainly used internally, but available
- /// publicly for convenience.
- ///
- public NumberFormatInfo NumberFormatInfo
- {
- get
- {
- if (_numberFormatInfo == null)
- {
- _numberFormatInfo = CultureInfo.InvariantCulture.NumberFormat.Clone() as NumberFormatInfo;
- _numberFormatInfo.NumberGroupSeparator = "";
- }
- return _numberFormatInfo;
- }
- }
-
- ///
- /// Gets whether the exporter is currently processing.
- ///
- [XmlIgnore]
- public bool IsProcessing { get; private set; }
-
- ///
- /// Gets the number of cells that were already processed
- /// during export.
- ///
- [XmlIgnore]
- public long CellsProcessed { get; private set; }
-
- ///
- /// Gets the total number of cells to export.
- ///
- [XmlIgnore]
- public long CellsTotal { get; private set; }
-
- #endregion
-
- #region Constructor
-
- public CsvFile()
- {
- FieldSeparator = ",";
- DecimalSeparator = ".";
- ThousandsSeparator = "";
- }
-
- #endregion
-
- #region Import/export methods
-
- public void Import()
- {
- Logger.Info("Importing CSV: FS='{0}', DS='{1}', TS='{2}'",
- FieldSeparator, DecimalSeparator, ThousandsSeparator);
- UserSettings.UserSettings.Default.CsvImport = this;
- Excel.ViewModels.Instance.Default.Application.Workbooks.OpenText(
- FileName,
- DataType: XlTextParsingType.xlDelimited,
- Other: true, OtherChar: StringParam(FieldSeparator),
- DecimalSeparator: StringParam(DecimalSeparator),
- ThousandsSeparator: StringParam(ThousandsSeparator),
- Local: false, ConsecutiveDelimiter: false,
- Origin: XlPlatform.xlWindows
- );
- }
-
- ///
- /// Exports the used range of the active worksheet to a CSV file,
- /// using the file name specified in the property.
- ///
- public void Export()
- {
- Worksheet worksheet = Excel.ViewModels.Instance.Default.ActiveWorkbook.ActiveSheet as Worksheet;
- if (worksheet == null)
- {
- throw new InvalidOperationException("Cannot export chart to CSV file.");
- }
- Export(worksheet.UsedRange);
- }
-
- ///
- /// Exports a range to a CSV file, using the file name specified
- /// in the property.
- ///
- /// Range to export.
- public void Export(Range range)
- {
- Logger.Info("Exporting CSV: FS='{0}', DS='{1}', TS='{2}'",
- FieldSeparator, DecimalSeparator, ThousandsSeparator);
- UserSettings.UserSettings.Default.CsvExport = this;
- IsProcessing = true;
- Task t = new Task(() =>
- {
- StreamWriter sw = null;
- try
- {
- // StreamWriter buffers the output; using a StringBuilder
- // doesn't speed up things (tried it)
- sw = File.CreateText(FileName);
- CellsTotal = range.CellsCount();
- Logger.Info("Number of cells: {0}", CellsTotal);
- CellsProcessed = 0;
- _cancelExport = false;
- string fs = FieldSeparator;
- if (fs == "\\t") { fs = "\t"; } // Convert "\t" to tab characters
-
-
- // Get all values in an array
- foreach (Range row in range.Rows)
- {
- // object[,] values = range.Value2;
- object[,] values = row.Value2;
- if (values != null)
- {
- //for (long row = 1; row <= values.GetLength(0); row++)
- //{
- for (long col = 1; col <= values.GetLength(1); col++)
- {
- CellsProcessed++;
-
- // If this is not the first field in the line, write a field separator.
- if (col > 1)
- {
- sw.Write(fs);
- }
-
- // object value = values[row, col];
- object value = values[1, col]; // 1-based index!
- if (value != null)
- {
- if (value is string)
- {
- string s = value as string;
- if (s.Contains(fs) || s.Contains("\""))
- {
- s = "\"" + s.Replace("\"", "\"\"") + "\"";
- }
- sw.Write(s);
- }
- else
- {
- double d = Convert.ToDouble(value);
- sw.Write(d.ToString(NumberFormatInfo));
- }
- }
- if (_cancelExport) break;
- }
- sw.WriteLine();
- }
- if (_cancelExport)
- {
- sw.WriteLine(UNFINISHED_EXPORT);
- sw.WriteLine("Cancelled by user.");
- Logger.Info("CSV export cancelled by user");
- break;
- }
- // }
- }
- sw.Close();
- if (!_cancelExport) OnProcessSucceeded();
- }
- catch (IOException e)
- {
- IsProcessing = false;
- OnProcessFailed(e);
- }
- catch (Exception e1)
- {
- IsProcessing = false;
- if (sw != null)
- {
- sw.WriteLine(UNFINISHED_EXPORT);
- sw.WriteLine(e1.ToString());
- sw.Close();
- }
- OnProcessFailed(e1);
- }
- finally
- {
- IsProcessing = false;
- Logger.Info("CSV export task finished");
- }
- });
- t.Start();
- }
-
- public void CancelExport()
- {
- _cancelExport = true;
- }
-
- #endregion
-
- #region Private methods
-
- ///
- /// Helper function that converts empty strings to Type.Missing.
- ///
- /// String to convert.
- /// String or Type.Missing if string is null or empty.
- /// This function is necessary because Workbooks.OpenText will
- /// throw a COM exception if one of the optional parameters is an empty
- /// string.
- ///
- object StringParam(string s)
- {
- if (String.IsNullOrEmpty(s))
- {
- return Type.Missing;
- }
- else
- {
- return s;
- }
- }
-
- #endregion
-
- #region Fields
-
- NumberFormatInfo _numberFormatInfo;
- bool _cancelExport;
-
- #endregion
-
- #region Private constant
-
- const string UNFINISHED_EXPORT = "*** UNFINISHED EXPORT ***";
- #endregion
- }
-}
diff --git a/XLToolbox/Csv/CsvFileBase.cs b/XLToolbox/Csv/CsvFileBase.cs
new file mode 100755
index 00000000..fc8b8543
--- /dev/null
+++ b/XLToolbox/Csv/CsvFileBase.cs
@@ -0,0 +1,131 @@
+/* CsvFile.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.IO;
+using Microsoft.Office.Interop.Excel;
+using System.Globalization;
+using XLToolbox.Excel;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace XLToolbox.Csv
+{
+ ///
+ /// Provides import/export settings and methods for CSV files.
+ ///
+ public abstract class CsvFileBase : Bovender.Mvvm.Models.ProcessModel
+ {
+ #region Properties
+
+ public string FileName { get; set; }
+
+ public string FieldSeparator
+ {
+ get
+ {
+ return Settings.FieldSeparator;
+ }
+ set
+ {
+ Settings.FieldSeparator = value;
+ }
+ }
+
+ public string DecimalSeparator
+ {
+ get
+ {
+ return Settings.DecimalSeparator;
+ }
+ set
+ {
+ Settings.DecimalSeparator = value;
+ }
+ }
+
+ public string ThousandsSeparator
+ {
+ get
+ {
+ return Settings.ThousandsSeparator;
+ }
+ set
+ {
+ Settings.ThousandsSeparator = value;
+ }
+ }
+
+ public CsvSettings Settings
+ {
+ get
+ {
+ if (_settings == null)
+ {
+ _settings = new CsvSettings();
+ }
+ return _settings;
+ }
+ set
+ {
+ _settings = value;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Instantiates the class with a new CsvSettings object.
+ ///
+ protected CsvFileBase()
+ : base()
+ { }
+
+ ///
+ /// Instantiates the class with a given CsvSettings object.
+ ///
+ /// Settings to initialize the
+ /// class with.
+ protected CsvFileBase(CsvSettings settings)
+ : this()
+ {
+ Settings = settings;
+ }
+
+ #endregion
+
+ #region Protected property
+
+ protected NumberFormatInfo NumberFormatInfo
+ {
+ get
+ {
+ return Settings.NumberFormatInfo;
+ }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ private CsvSettings _settings;
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/Csv/CsvImportViewModel.cs b/XLToolbox/Csv/CsvImportViewModel.cs
index b74a7a31..742f97b7 100755
--- a/XLToolbox/Csv/CsvImportViewModel.cs
+++ b/XLToolbox/Csv/CsvImportViewModel.cs
@@ -22,16 +22,17 @@
using Bovender.Mvvm.ViewModels;
using Bovender.Mvvm.Messaging;
using Bovender.Mvvm;
+using System.Diagnostics;
namespace XLToolbox.Csv
{
- class CsvImportViewModel : ViewModelBase
+ public class CsvImportViewModel : ProcessViewModelBase
{
#region Factory
public static CsvImportViewModel FromLastUsed()
{
- return new CsvImportViewModel(CsvFile.LastImport());
+ return new CsvImportViewModel(CsvImporter.LastImport());
}
#endregion
@@ -40,40 +41,40 @@ public static CsvImportViewModel FromLastUsed()
public string FileName
{
- get { return _csvFile.FileName; }
+ get { return Importer.FileName; }
set
{
- _csvFile.FileName = value;
+ Importer.FileName = value;
OnPropertyChanged("FileName");
}
}
public string FieldSeparator
{
- get { return _csvFile.FieldSeparator; }
+ get { return Importer.FieldSeparator; }
set
{
- _csvFile.FieldSeparator = value;
+ Importer.FieldSeparator = value;
OnPropertyChanged("FieldSeparator");
}
}
public string DecimalSeparator
{
- get { return _csvFile.DecimalSeparator; }
+ get { return Importer.DecimalSeparator; }
set
{
- _csvFile.DecimalSeparator = value;
+ Importer.DecimalSeparator = value;
OnPropertyChanged("DecimalSeparator");
}
}
public string ThousandsSeparator
{
- get { return _csvFile.ThousandsSeparator; }
+ get { return Importer.ThousandsSeparator; }
set
{
- _csvFile.ThousandsSeparator = value;
+ Importer.ThousandsSeparator = value;
OnPropertyChanged("ThousandsSeparator");
}
}
@@ -129,21 +130,19 @@ public Message ChooseImportFileNameMessage
#region Constructors
public CsvImportViewModel()
- : this(new CsvFile()) { }
+ : this(new CsvImporter()) { }
- protected CsvImportViewModel(CsvFile model)
- : base()
- {
- _csvFile = model;
- }
+ protected CsvImportViewModel(CsvImporter model)
+ : base(model)
+ { }
#endregion
- #region ViewModelBase implementation
+ #region ProcessViewModelBase implementation
- public override object RevealModelObject()
+ protected override int GetPercentCompleted()
{
- return _csvFile;
+ return 50; // TODO
}
#endregion
@@ -164,7 +163,7 @@ private void ConfirmChooseFileName(FileNameMessageContent messageContent)
{
if (messageContent.Confirmed)
{
- _csvFile.FileName = messageContent.Value;
+ Importer.FileName = messageContent.Value;
DoImport();
}
}
@@ -175,15 +174,26 @@ private void DoImport()
{
store.Put("csv_path", System.IO.Path.GetDirectoryName(FileName));
}
- _csvFile.Import();
+ Importer.Execute();
CloseViewCommand.Execute(null);
}
#endregion
+ #region Private properties
+
+ private CsvImporter Importer
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ return ProcessModel as CsvImporter;
+ }
+ }
+ #endregion
+
#region Private fields
- CsvFile _csvFile;
DelegatingCommand _chooseFileNameCommand;
DelegatingCommand _importCommand;
Message _chooseImportFileNameMessage;
diff --git a/XLToolbox/Csv/CsvImporter.cs b/XLToolbox/Csv/CsvImporter.cs
new file mode 100755
index 00000000..33f40b9f
--- /dev/null
+++ b/XLToolbox/Csv/CsvImporter.cs
@@ -0,0 +1,112 @@
+using Microsoft.Office.Interop.Excel;
+/* CsvImporter.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace XLToolbox.Csv
+{
+ public class CsvImporter : CsvFileBase
+ {
+ #region Factory
+
+ public static CsvImporter LastImport()
+ {
+ CsvSettings settings = UserSettings.UserSettings.Default.CsvSettings;
+ if (settings == null)
+ {
+ return new CsvImporter();
+ }
+ else
+ {
+ return new CsvImporter(settings);
+ }
+ }
+
+ #endregion
+
+ #region Implementation of ProcessModel
+
+ public override bool Execute()
+ {
+ Logger.Info("Importing CSV: FS='{0}', DS='{1}', TS='{2}'",
+ FieldSeparator, DecimalSeparator, ThousandsSeparator);
+ UserSettings.UserSettings.Default.CsvSettings = Settings;
+ Excel.ViewModels.Instance.Default.Application.Workbooks.OpenText(
+ FileName,
+ DataType: XlTextParsingType.xlDelimited,
+ Other: true, OtherChar: StringParam(FieldSeparator),
+ DecimalSeparator: StringParam(DecimalSeparator),
+ ThousandsSeparator: StringParam(ThousandsSeparator),
+ Local: false, ConsecutiveDelimiter: false,
+ Origin: XlPlatform.xlWindows
+ );
+ return true;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ public CsvImporter()
+ : base()
+ { }
+
+ public CsvImporter(CsvSettings settings)
+ : base(settings)
+ { }
+
+ #endregion
+
+ #region Private methods
+
+ ///
+ /// Helper function that converts empty strings to Type.Missing.
+ ///
+ /// String to convert.
+ /// String or Type.Missing if string is null or empty.
+ /// This function is necessary because Workbooks.OpenText will
+ /// throw a COM exception if one of the optional parameters is an empty
+ /// string.
+ ///
+ object StringParam(string s)
+ {
+ if (String.IsNullOrEmpty(s))
+ {
+ return Type.Missing;
+ }
+ else
+ {
+ return s;
+ }
+ }
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/Csv/CsvSettings.cs b/XLToolbox/Csv/CsvSettings.cs
new file mode 100755
index 00000000..71c5a4ce
--- /dev/null
+++ b/XLToolbox/Csv/CsvSettings.cs
@@ -0,0 +1,84 @@
+/* CsvSettings.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace XLToolbox.Csv
+{
+ public class CsvSettings
+ {
+ #region Public properties
+
+ public string FieldSeparator { get; set; }
+
+ public string DecimalSeparator
+ {
+ get { return NumberFormatInfo.NumberDecimalSeparator; }
+ set { NumberFormatInfo.NumberDecimalSeparator = value; }
+ }
+
+ public string ThousandsSeparator
+ {
+ get { return NumberFormatInfo.NumberGroupSeparator; }
+ set { NumberFormatInfo.NumberGroupSeparator = value; }
+ }
+
+ ///
+ /// Returns a System.Globalization.NumberFormatInfo object
+ /// whose properties are set according to the current
+ /// properties (namely, .)
+ /// This property is mainly used internally, but available
+ /// publicly for convenience.
+ ///
+ [YamlDotNet.Serialization.YamlIgnore]
+ public NumberFormatInfo NumberFormatInfo
+ {
+ get
+ {
+ if (_numberFormatInfo == null)
+ {
+ _numberFormatInfo = CultureInfo.InvariantCulture.NumberFormat.Clone() as NumberFormatInfo;
+ _numberFormatInfo.NumberGroupSeparator = "";
+ }
+ return _numberFormatInfo;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public CsvSettings()
+ {
+ FieldSeparator = ",";
+ DecimalSeparator = ".";
+ ThousandsSeparator = "";
+ }
+
+ #endregion
+
+ #region Fields
+
+ private NumberFormatInfo _numberFormatInfo;
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/Dispatcher.cs b/XLToolbox/Dispatcher.cs
index 4abd48d0..718f233f 100755
--- a/XLToolbox/Dispatcher.cs
+++ b/XLToolbox/Dispatcher.cs
@@ -65,7 +65,7 @@ public static void Execute(Command cmd)
case Command.BatchExportLast: BatchExportLast(); break;
case Command.ExportScreenshot: ExportScreenshot(); break;
case Command.Donate: OpenDonatePage(); break;
- case Command.ThrowError: throw new InsufficientMemoryException();
+ case Command.ThrowError: throw new ExceptionHandler.TestException("This exception was thrown for testing purposes");
case Command.QuitExcel: QuitExcel(); break;
case Command.OpenCsv: OpenCsv(); break;
case Command.OpenCsvWithParams: OpenCsvWithSettings(); break;
@@ -154,7 +154,7 @@ static void CheckForUpdates()
static void SheetManager()
{
- SheetManagerPane.Default.Visible = true;
+ TaskPaneManager.Default.Visible = true;
// wvm.InjectAndShowInThread();
}
@@ -167,8 +167,8 @@ static void ExportSelection()
}
SingleExportSettings settings = SingleExportSettings.CreateForSelection(preset);
SingleExportSettingsViewModel vm = new SingleExportSettingsViewModel(settings);
- vm.ShowProgressMessage.Sent += ShowProgressMessage_Sent;
- vm.ProcessFailedMessage.Sent += ProcessFailedMessage_Sent;
+ vm.ShowProgressMessage.Sent += Exporter_ShowProgress_Sent;
+ vm.ProcessFinishedMessage.Sent += Exporter_ProcessFinished_Sent;
vm.InjectInto().ShowDialogInForm();
}
@@ -187,8 +187,8 @@ static void BatchExport()
vm = new BatchExportSettingsViewModel();
}
vm.SanitizeOptions();
- vm.ShowProgressMessage.Sent += ShowProgressMessage_Sent;
- vm.ProcessFailedMessage.Sent += ProcessFailedMessage_Sent;
+ vm.ShowProgressMessage.Sent += Exporter_ShowProgress_Sent;
+ vm.ProcessFinishedMessage.Sent += Exporter_ProcessFinished_Sent;
vm.InjectInto().ShowDialogInForm();
}
@@ -385,19 +385,22 @@ static Csv.CsvExportViewModel CreateCsvExportViewModel(Xl.Range range)
};
args.Content.InjectInto().Show();
};
- vm.ProcessFailedMessage.Sent += (sender, args) =>
+ vm.ProcessFinishedMessage.Sent += (sender, args) =>
{
- Logger.Info("Received ExportFailedMessage, informing user");
- Bovender.Mvvm.Actions.ProcessCompletedAction action = new ProcessCompletedAction(
- args.Content, Strings.CsvExportFailed, Strings.CsvExportFailed, Strings.Close);
- action.Invoke(args);
+ if (args.Content.Exception != null)
+ {
+ Logger.Info("Received ProcessFinishedMessage with exception");
+ Bovender.Mvvm.Actions.ProcessCompletedAction action = new ProcessCompletedAction(
+ args.Content, Strings.CsvExportFailed, Strings.CsvExportFailed, Strings.Close);
+ action.Invoke(args);
+ }
};
return vm;
}
- internal static void ShowProgressMessage_Sent(object sender, MessageArgs e)
+ internal static void Exporter_ShowProgress_Sent(object sender, MessageArgs e)
{
- Logger.Info("Creating process view");
+ Logger.Info("Exporter_ShowProgress_Sent: Creating process view");
e.Content.CancelButtonText = Strings.Cancel;
e.Content.Caption = Strings.Export;
e.Content.CompletedMessage.Sent += (sender2, args2) =>
@@ -407,12 +410,19 @@ internal static void ShowProgressMessage_Sent(object sender, MessageArgs().ShowDialogInForm();
}
- internal static void ProcessFailedMessage_Sent(object sender, MessageArgs e)
+ internal static void Exporter_ProcessFinished_Sent(object sender, MessageArgs e)
{
- Logger.Info("Received ExportFailedMessage, informing user");
- Bovender.Mvvm.Actions.ProcessCompletedAction action = new ProcessCompletedAction(
- e.Content, Strings.ExportFailed, Strings.ExportFailedMessage, Strings.Close);
- action.Invoke(e);
+ if (e.Content.Exception != null)
+ {
+ Logger.Info("Exporter_ProcessFinished_Sent: Received ProcessFinishedMessage with exception, informing user");
+ Bovender.Mvvm.Actions.ProcessCompletedAction action = new ProcessCompletedAction(
+ e.Content, Strings.ExportFailed, Strings.ExportFailedMessage, Strings.Close);
+ action.Invoke(e);
+ }
+ else
+ {
+ Logger.Info("Exporter_ProcessFinished_Sent: Exporter process has finished");
+ }
}
#endregion
diff --git a/XLToolbox/Excel/ViewModels/Instance.cs b/XLToolbox/Excel/ViewModels/Instance.cs
index 2c618daa..423524ff 100755
--- a/XLToolbox/Excel/ViewModels/Instance.cs
+++ b/XLToolbox/Excel/ViewModels/Instance.cs
@@ -25,6 +25,7 @@
using Bovender.Mvvm.Messaging;
using System.Diagnostics;
using System.IO;
+using System.Globalization;
namespace XLToolbox.Excel.ViewModels
{
@@ -58,6 +59,12 @@ public static Instance Default
#endregion
+ #region Events
+
+ public event EventHandler ShuttingDown;
+
+ #endregion
+
#region Commands
public DelegatingCommand QuitInteractivelyCommand
@@ -169,6 +176,24 @@ public string ActivePath
}
}
+ ///
+ /// Gets the major version number of the Excel instance
+ /// as an integer.
+ ///
+ public int MajorVersion
+ {
+ get
+ {
+ if (_majorVersion == 0)
+ {
+ _majorVersion = Convert.ToInt32(
+ Application.Version.Split('.')[0],
+ CultureInfo.InvariantCulture);
+ }
+ return _majorVersion;
+ }
+ }
+
///
/// Gets the Excel version and build number in a human-friendly form.
///
@@ -183,39 +208,39 @@ public string HumanFriendlyVersion
{
get
{
- Application app = Application;
- string name = String.Empty;
- string sp = String.Empty;
- switch (Convert.ToInt32(app.Version.Split('.')[0]))
+ string versionName = String.Empty;
+ string servicePack = String.Empty;
+ int build = Application.Build;
+ switch (MajorVersion)
{
// Very old versions are ignored (won't work with VSTO anyway)
- case 11: name = "2003"; break;
- case 12: name = "2007"; break;
- case 14: name = "2010"; break;
- case 15: name = "2013"; break;
- case 16: name = "365"; break; // I believe (sparse information on the web)
- }
- int build = app.Build;
- switch (app.Version)
- {
- case "15.0":
- // 2013 SP information: http://support.microsoft.com/kb/2817430/en-us
- if (build >= 4569) { sp = " SP1"; }
+ case 11:
+ versionName = "2003";
+ break;
+ case 12:
+ versionName = "2007";
+ // 2007 SP information: http://support.microsoft.com/kb/928116/en-us
+ if (build >= 6611) { servicePack = " SP3"; }
+ else if (build >= 6425) { servicePack = " SP2"; }
+ else if (build >= 6241) { servicePack = " SP1"; }
break;
- case "14.0":
+ case 14:
// 2010 SP information: http://support.microsoft.com/kb/2121559/en-us
- if (build >= 7015) { sp = " SP2"; }
- else if (build >= 6029) { sp = " SP1"; }
+ versionName = "2010";
+ if (build >= 7015) { servicePack = " SP2"; }
+ else if (build >= 6029) { servicePack = " SP1"; }
break;
- case "12.0":
- // 2007 SP information: http://support.microsoft.com/kb/928116/en-us
- if (build >= 6611) { sp = " SP3"; }
- else if (build >= 6425) { sp = " SP2"; }
- else if (build >= 6241) { sp = " SP1"; }
+ case 15:
+ // 2013 SP information: http://support.microsoft.com/kb/2817430/en-us
+ versionName = "2013";
+ if (build >= 4569) { servicePack = " SP1"; }
break;
+ case 16:
+ versionName = "365";
+ break; // I believe (sparse information on the web)
}
return String.Format("{0}{1} ({2}.{3})",
- name, sp, app.Version, app.Build);
+ versionName, servicePack, Application.Version, Application.Build);
}
}
@@ -294,6 +319,18 @@ public int CountSavedWorkbooks
}
}
+ ///
+ /// Gets whether the current Excel instance has an SDI (Excel 2013+)
+ /// or not (Excel 2007/2010).
+ ///
+ public bool IsSingleDocumentInterface
+ {
+ get
+ {
+ return MajorVersion >= 15;
+ }
+ }
+
#endregion
#region Public methods
@@ -510,17 +547,36 @@ public override object RevealModelObject()
/// Shuts down the current instance of Excel; no warning message will be shown.
/// If an instance of this class exists, an error will be thrown.
///
- void Shutdown()
+ private void Shutdown()
{
if (_application != null)
{
_application.DisplayAlerts = false;
- Logger.Info("Now quitting Excel.");
- _application.Quit();
+ OnShuttingDown();
+ Logger.Info("Shutdown: Now quitting Excel.");
+ System.Threading.Timer t = new System.Threading.Timer((obj) =>
+ {
+ ((Application)obj).Quit();
+ }, _application, 150, System.Threading.Timeout.Infinite);
+ // _application.Quit();
_application = null;
}
}
+ private void OnShuttingDown()
+ {
+ EventHandler h = ShuttingDown;
+ if (h != null)
+ {
+ Logger.Info("OnShuttingDown: {0} event subscriber(s)", h.GetInvocationList().Length);
+ h(this, new InstanceShutdownEventArgs(Application));
+ }
+ else
+ {
+ Logger.Info("OnShuttingDown: No-one is listening.");
+ }
+ }
+
private void DoQuitInteractively()
{
Logger.Info("DoQuitInteractively");
@@ -613,13 +669,13 @@ private bool CloseAllWorkbooksThenShutdown()
// Try if the workbook has been closed
if (n == CountOpenWorkbooks) return false;
}
- Logger.Info("Examining the situation.");
+ Logger.Info("CloseAllWorkbooksThenShutdown: Examining the situation.");
if (Application.Workbooks.Count == 0)
{
Logger.Info("No more workbooks left.");
CloseViewCommand.Execute(null);
Shutdown();
- Logger.Info("Shutting down.");
+ Logger.Info("CloseAllWorkbooksThenShutdown: Shutting down.");
return true;
}
else
@@ -635,6 +691,7 @@ private bool CloseAllWorkbooksThenShutdown()
private bool _disposed;
private Application _application;
+ private int _majorVersion;
private DelegatingCommand _quitInteractivelyCommand;
private DelegatingCommand _quitSavingChangesCommand;
private DelegatingCommand _quitDiscardingChangesCommand;
diff --git a/XLToolbox/Excel/ViewModels/InstanceShutdownEventArgs.cs b/XLToolbox/Excel/ViewModels/InstanceShutdownEventArgs.cs
new file mode 100755
index 00000000..36d1da1b
--- /dev/null
+++ b/XLToolbox/Excel/ViewModels/InstanceShutdownEventArgs.cs
@@ -0,0 +1,35 @@
+using Microsoft.Office.Interop.Excel;
+/* InstanceShutdownEventArgs.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace XLToolbox.Excel.ViewModels
+{
+ public class InstanceShutdownEventArgs : EventArgs
+ {
+ public Application Application { get; private set; }
+
+ public InstanceShutdownEventArgs(Application application)
+ {
+ Application = application;
+ }
+ }
+}
diff --git a/XLToolbox/Excel/ViewModels/WorkbookViewModel.cs b/XLToolbox/Excel/ViewModels/WorkbookViewModel.cs
index 1b086751..514213bf 100755
--- a/XLToolbox/Excel/ViewModels/WorkbookViewModel.cs
+++ b/XLToolbox/Excel/ViewModels/WorkbookViewModel.cs
@@ -16,15 +16,14 @@
* limitations under the License.
*/
using System;
-using System.Collections.ObjectModel;
using System.ComponentModel;
+using System.Linq;
+using System.Collections.ObjectModel;
using Microsoft.Office.Interop.Excel;
using Bovender.Mvvm;
using Bovender.Mvvm.ViewModels;
using Bovender.Mvvm.Messaging;
-using System.Text;
using System.Threading;
-using System.Threading.Tasks;
namespace XLToolbox.Excel.ViewModels
{
@@ -34,59 +33,6 @@ namespace XLToolbox.Excel.ViewModels
///
public class WorkbookViewModel : ViewModelBase
{
- ///
- /// Interval at which to refresh the sheet list when monitoring
- /// the Workbook (see command,
- /// method).
- ///
- const int MONITOR_INTERVAL = 700; // ms
-
- #region Private fields
-
- private Workbook _workbook;
- private ObservableCollection _sheets;
- private SheetViewModel _lastSelectedSheet;
- private DelegatingCommand _moveSheetUp;
- private DelegatingCommand _moveSheetsToTop;
- private DelegatingCommand _moveSheetDown;
- private DelegatingCommand _moveSheetsToBottom;
- private DelegatingCommand _deleteSheets;
- private DelegatingCommand _renameSheet;
- private DelegatingCommand _monitorWorkbook;
- private DelegatingCommand _unmonitorWorkbook;
- private Message _confirmDeleteMessage;
- private Message _renameSheetMessage;
- private bool _monitoring;
- private string _lastSheetsString;
-
- #endregion
-
- #region Protected properties
-
- protected Workbook Workbook
- {
- get
- {
- return _workbook;
- }
- set
- {
- _workbook = value;
- OnPropertyChanged("Workbook");
- BuildSheetList();
- if (_workbook != null)
- {
- DisplayString = _workbook.Name;
- }
- else
- {
- DisplayString = String.Empty;
- }
- }
- }
-
- #endregion
-
#region Public properties
public int NumSelectedSheets { get; private set; }
@@ -310,8 +256,16 @@ public DelegatingCommand UnmonitorWorkbook
public WorkbookViewModel()
{
- Excel.ViewModels.Instance.Default.Application.WorkbookActivate += Application_WorkbookActivate;
- Excel.ViewModels.Instance.Default.Application.WorkbookDeactivate += Application_WorkbookDeactivate;
+ if (!XLToolbox.Excel.ViewModels.Instance.Default.IsSingleDocumentInterface)
+ {
+ // Change the workbook model only if this is not an SDI application
+ Excel.ViewModels.Instance.Default.Application.WorkbookActivate += Application_WorkbookActivate;
+ Excel.ViewModels.Instance.Default.Application.WorkbookDeactivate += Application_WorkbookDeactivate;
+ }
+ Instance.Default.ShuttingDown += (sender, args) =>
+ {
+ DoUnmonitorWorkbook();
+ };
}
public WorkbookViewModel(Workbook workbook)
@@ -322,6 +276,15 @@ public WorkbookViewModel(Workbook workbook)
#endregion
+ #region Implementation of ViewModelBase's abstract methods
+
+ public override object RevealModelObject()
+ {
+ return _workbook;
+ }
+
+ #endregion
+
#region Protected methods
protected void BuildSheetList()
@@ -333,8 +296,8 @@ protected void BuildSheetList()
SheetViewModel svm;
foreach (dynamic sheet in Workbook.Sheets)
{
- // Directly comparing the Visible property with XlSheetVisibility.xlSheetVisible
- // caused exceptions. Therefore we compare directly with the value of 0.
+ // Need to cats because directly comparing the Visible property with
+ // XlSheetVisibility.xlSheetVisible caused exceptions.
if ((XlSheetVisibility)sheet.Visible == XlSheetVisibility.xlSheetVisible)
{
svm = new SheetViewModel(sheet);
@@ -342,7 +305,9 @@ protected void BuildSheetList()
sheets.Add(svm);
}
};
+ Workbook.SheetActivate += SheetActivated;
Sheets = sheets;
+ SheetActivated(Workbook.ActiveSheet);
}
else
{
@@ -388,6 +353,7 @@ void Application_WorkbookDeactivate(Workbook Wb)
private void DoMoveSheetUp()
{
+ _lockEvents = true;
// When iterating over the worksheet view models in the Sheets collection
// as well as over the sheets collection of the workbook, keep in mind
// that Excel workbook collections are 1-based.
@@ -399,10 +365,12 @@ private void DoMoveSheetUp()
Sheets.Move(i, i - 1);
}
}
+ _lockEvents = false;
}
private void DoMoveSheetsToTop()
{
+ _lockEvents = true;
int currentTop = 0;
for (int i = 1; i < Sheets.Count; i++)
{
@@ -413,6 +381,7 @@ private void DoMoveSheetsToTop()
currentTop++;
}
}
+ _lockEvents = false;
}
private bool CanMoveSheetUp()
@@ -427,6 +396,7 @@ private bool CanMoveSheetsToTop()
private void DoMoveSheetDown()
{
+ _lockEvents = true;
// When iterating over the worksheet view models in the Sheets collection
// as well as over the sheets collection of the workbook, keep in mind
// that Excel workbook collections are 1-based.
@@ -438,10 +408,12 @@ private void DoMoveSheetDown()
Sheets.Move(i, i + 1);
}
}
+ _lockEvents = false;
}
private void DoMoveSheetsToBottom()
{
+ _lockEvents = true;
int currentBottom = Sheets.Count - 1;
for (int i = currentBottom-1; i >= 0; i--)
{
@@ -452,6 +424,7 @@ private void DoMoveSheetsToBottom()
currentBottom--;
}
}
+ _lockEvents = false;
}
private bool CanMoveSheetDown()
@@ -500,6 +473,7 @@ private bool CanDeleteSheets()
private void DoRenameSheet()
{
+ Logger.Info("DoRenameSheet");
StringMessageContent content = new StringMessageContent();
content.Value = _lastSelectedSheet.DisplayString;
content.Validator = (value) =>
@@ -527,8 +501,13 @@ private void ConfirmRenameSheet(StringMessageContent stringMessage)
{
if (CanRenameSheet() && stringMessage.Confirmed)
{
+ Logger.Info("ConfirmRenameSheet: confirmed");
_lastSelectedSheet.DisplayString = stringMessage.Value;
}
+ else
+ {
+ Logger.Info("ConfirmRenameSheet: not confirmed or unable to rename sheet");
+ }
}
private bool CanRenameSheet()
@@ -538,57 +517,113 @@ private bool CanRenameSheet()
private void DoMonitorWorkbook()
{
- if (!_monitoring)
+ if (_timer == null)
{
Logger.Info("Begin monitoring workbook");
- _monitoring = true;
- Task.Factory.StartNew(() =>
- {
- while (_monitoring)
- {
- CheckSheetsChanged();
- Thread.Sleep(MONITOR_INTERVAL);
- }
- });
+ _timer = new Timer(
+ CheckSheetsChanged,
+ null,
+ Properties.Settings.Default.WorkbookMonitorIntervalMilliseconds,
+ Properties.Settings.Default.WorkbookMonitorIntervalMilliseconds);
}
}
private bool CanMonitorWorkbook()
{
- return _workbook != null && !_monitoring;
+ return _workbook != null && _timer == null;
}
private void DoUnmonitorWorkbook()
{
- Logger.Info("Stop monitoring workbook");
- _monitoring = false;
- CheckSheetsChanged();
+ if (_timer != null)
+ {
+ Logger.Info("Stop monitoring workbook");
+ _timer.Dispose();
+ _timer = null;
+ CheckSheetsChanged(null);
+ }
}
private bool CanUnmonitorWorkbook()
{
- return _monitoring;
+ return _timer == null;
}
- private void CheckSheetsChanged()
+ private void CheckSheetsChanged(object state)
{
- string sheetsString = SheetsString;
- if (sheetsString != _lastSheetsString)
+ if (!_lockEvents)
{
- _lastSheetsString = sheetsString;
- BuildSheetList();
+ string sheetsString = SheetsString;
+ if (sheetsString != _lastSheetsString)
+ {
+ Logger.Info("CheckSheetsChanged: Change in worksheets detected, rebuilding list");
+ _lastSheetsString = sheetsString;
+ BuildSheetList();
+ }
+ }
+ }
+
+ private void SheetActivated(dynamic sheet)
+ {
+ if (sheet != null && !_lockEvents)
+ {
+ SheetViewModel svm = Sheets.FirstOrDefault(s => s.IsSelected);
+ if (svm != null)
+ {
+ svm.IsSelected = false;
+ }
+ // Excel collection indexes are 1-based; .NET 0-based.
+ Sheets[sheet.Index - 1].IsSelected = true;
}
}
#endregion
- #region Implementation of ViewModelBase's abstract methods
+ #region Private fields
- public override object RevealModelObject()
+ private Workbook _workbook;
+ private ObservableCollection _sheets;
+ private SheetViewModel _lastSelectedSheet;
+ private DelegatingCommand _moveSheetUp;
+ private DelegatingCommand _moveSheetsToTop;
+ private DelegatingCommand _moveSheetDown;
+ private DelegatingCommand _moveSheetsToBottom;
+ private DelegatingCommand _deleteSheets;
+ private DelegatingCommand _renameSheet;
+ private DelegatingCommand _monitorWorkbook;
+ private DelegatingCommand _unmonitorWorkbook;
+ private Message _confirmDeleteMessage;
+ private Message _renameSheetMessage;
+ private string _lastSheetsString;
+ private Timer _timer;
+ private bool _lockEvents;
+
+ #endregion
+
+ #region Protected properties
+
+ protected Workbook Workbook
{
- return _workbook;
+ get
+ {
+ return _workbook;
+ }
+ set
+ {
+ _workbook = value;
+ OnPropertyChanged("Workbook");
+ BuildSheetList();
+ if (_workbook != null)
+ {
+ DisplayString = _workbook.Name;
+ }
+ else
+ {
+ DisplayString = String.Empty;
+ }
+ }
}
-
+
#endregion
#region Class logger
diff --git a/XLToolbox/ExceptionHandler/TestException.cs b/XLToolbox/ExceptionHandler/TestException.cs
new file mode 100755
index 00000000..20e60e7d
--- /dev/null
+++ b/XLToolbox/ExceptionHandler/TestException.cs
@@ -0,0 +1,35 @@
+/* TestException.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace XLToolbox.ExceptionHandler
+{
+ [Serializable]
+ class TestException : Exception
+ {
+ public TestException() { }
+ public TestException(string message) : base(message) { }
+ public TestException(string message,
+ Exception innerException)
+ : base(message, innerException) { }
+ public TestException(SerializationInfo info,
+ StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/XLToolbox/Export/BatchExporter.cs b/XLToolbox/Export/BatchExporter.cs
new file mode 100755
index 00000000..144574df
--- /dev/null
+++ b/XLToolbox/Export/BatchExporter.cs
@@ -0,0 +1,317 @@
+using Microsoft.Office.Interop.Excel;
+/* BatchExporter.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using XLToolbox.Excel.ViewModels;
+using XLToolbox.Export.Models;
+
+namespace XLToolbox.Export
+{
+ public class BatchExporter : Bovender.Mvvm.Models.ProcessModel
+ {
+ #region Public properties
+
+ public BatchExportSettings Settings { get; set; }
+
+ public int PercentCompleted
+ {
+ get
+ {
+ if (_batchFileName != null && _numTotal != 0)
+ {
+ return Convert.ToInt32(100d * _batchFileName.Counter / _numTotal);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public BatchExporter(BatchExportSettings settings)
+ : base()
+ {
+ Settings = settings;
+ _exporter = new Exporter(settings.Preset);
+ }
+
+ #endregion
+
+ #region Implementation of ProcessModel
+
+ public override bool Execute()
+ {
+ _batchFileName = new ExportFileName(
+ Settings.Path,
+ Settings.FileName,
+ Settings.Preset.FileType);
+ bool result = false;
+ try
+ {
+ Instance.Default.DisableScreenUpdating();
+ switch (Settings.Scope)
+ {
+ case BatchExportScope.ActiveSheet:
+ _numTotal = CountInSheet(Instance.Default.Application.ActiveSheet);
+ ExportSheet(Instance.Default.Application.ActiveSheet);
+ break;
+ case BatchExportScope.ActiveWorkbook:
+ _numTotal = CountInWorkbook(Instance.Default.ActiveWorkbook);
+ ExportWorkbook(Instance.Default.ActiveWorkbook);
+ break;
+ case BatchExportScope.OpenWorkbooks:
+ _numTotal = CountInAllWorkbooks();
+ ExportAllWorkbooks();
+ break;
+ default:
+ throw new NotImplementedException(String.Format(
+ "Batch export not implemented for {0}",
+ Settings.Scope));
+ }
+ Instance.Default.EnableScreenUpdating();
+ }
+ catch (Exception e)
+ {
+ Instance.Default.EnableScreenUpdating();
+ throw e;
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Private export methods
+
+ private void ExportAllWorkbooks()
+ {
+ foreach (Workbook wb in Instance.Default.Application.Workbooks)
+ {
+ ExportWorkbook(wb);
+ if (IsCancellationRequested) break;
+ }
+ }
+
+ private void ExportWorkbook(Workbook workbook)
+ {
+ ((_Workbook)workbook).Activate();
+ foreach (dynamic ws in workbook.Sheets)
+ {
+ ExportSheet(ws);
+ if (IsCancellationRequested) break;
+ }
+ }
+
+ private void ExportSheet(dynamic sheet)
+ {
+ sheet.Activate();
+ switch (Settings.Layout)
+ {
+ case BatchExportLayout.SheetLayout:
+ ExportSheetLayout(sheet);
+ break;
+ case BatchExportLayout.SingleItems:
+ ExportSheetItems(sheet);
+ break;
+ default:
+ throw new NotImplementedException(
+ String.Format("Export of {0} not implemented.", Settings.Layout)
+ );
+ }
+ }
+
+ private void ExportSheetLayout(dynamic sheet)
+ {
+ SheetViewModel svm = new SheetViewModel(sheet);
+ switch (Settings.Objects)
+ {
+ case BatchExportObjects.Charts:
+ svm.SelectCharts();
+ break;
+ case BatchExportObjects.ChartsAndShapes:
+ svm.SelectShapes();
+ break;
+ default:
+ throw new NotImplementedException(Settings.Objects.ToString());
+ }
+ _exporter.FileName = _batchFileName.GenerateNext(sheet);
+ _exporter.Execute();
+ }
+
+ private void ExportSheetItems(dynamic sheet)
+ {
+ SheetViewModel svm = new SheetViewModel(sheet);
+ if (svm.IsChart)
+ {
+ svm.SelectCharts();
+ ExportSelection(svm.Sheet);
+ }
+ else
+ {
+ switch (Settings.Objects)
+ {
+ case BatchExportObjects.Charts:
+ ExportSheetChartItems(svm.Worksheet);
+ break;
+ case BatchExportObjects.ChartsAndShapes:
+ ExportSheetAllItems(svm.Worksheet);
+ break;
+ default:
+ throw new NotImplementedException(
+ "Single-item export not implemented for " + Settings.Objects.ToString());
+ }
+ }
+ }
+
+ private void ExportSheetChartItems(Worksheet worksheet)
+ {
+ // Must use an index-based for loop here.
+ // A foreach loop caused lots of 0x800a03ec errors from Excel
+ // (for whatever reason).
+ ChartObjects cos = worksheet.ChartObjects();
+ for (int i = 1; i <= cos.Count; i++)
+ {
+ cos.Item(i).Select();
+ ExportSelection(worksheet);
+ if (IsCancellationRequested) break;
+ }
+ }
+
+ private void ExportSheetAllItems(Worksheet worksheet)
+ {
+ foreach (Shape sh in worksheet.Shapes)
+ {
+ sh.Select(true);
+ ExportSelection(worksheet);
+ if (IsCancellationRequested) break;
+ }
+ }
+
+ private void ExportSelection(dynamic sheet)
+ {
+ _exporter.FileName = _batchFileName.GenerateNext(sheet);
+ _exporter.Execute();
+ }
+
+ #endregion
+
+ #region Private counting methods
+
+ private int CountInAllWorkbooks()
+ {
+ int n = 0;
+ foreach (Workbook wb in Instance.Default.Application.Workbooks)
+ {
+ n += CountInWorkbook(wb);
+ }
+ return n;
+ }
+
+ private int CountInWorkbook(Workbook workbook)
+ {
+ int n = 0;
+ foreach (Worksheet ws in workbook.Worksheets)
+ {
+ n += CountInSheet(ws);
+ }
+ return n;
+ }
+
+ private int CountInSheet(dynamic worksheet)
+ {
+ switch (Settings.Layout)
+ {
+ case BatchExportLayout.SheetLayout:
+ return CountInSheetLayout(worksheet);
+ case BatchExportLayout.SingleItems:
+ return CountInSheetItems(worksheet);
+ default:
+ throw new NotImplementedException(
+ String.Format("Export of {0} not implemented.", Settings.Layout)
+ );
+ }
+ }
+
+ ///
+ /// Returns 1 if the contains at least
+ /// one chart or drawing object, since all charts/drawing objects will
+ /// be exported together into one file.
+ ///
+ /// Worksheet to examine.
+ /// 1 if sheet contains charts/drawings, 0 if not.
+ private int CountInSheetLayout(dynamic worksheet)
+ {
+ SheetViewModel svm = new SheetViewModel(worksheet);
+ switch (Settings.Objects)
+ {
+ case BatchExportObjects.Charts:
+ return svm.CountCharts() > 0 ? 1 : 0;
+ case BatchExportObjects.ChartsAndShapes:
+ return svm.CountShapes() > 0 ? 1 : 0;
+ default:
+ throw new NotImplementedException(String.Format(
+ "Export of {0} not implemented.", Settings.Objects));
+ }
+ }
+
+ private int CountInSheetItems(dynamic worksheet)
+ {
+ SheetViewModel svm = new SheetViewModel(worksheet);
+ switch (Settings.Objects)
+ {
+ case BatchExportObjects.Charts:
+ return svm.CountCharts();
+ case BatchExportObjects.ChartsAndShapes:
+ return svm.CountShapes();
+ default:
+ throw new NotImplementedException(String.Format(
+ "Export of {0} not implemented.", Settings.Objects));
+ }
+ }
+
+ /*private FREE_IMAGE_FORMAT FileTypeToFreeImage(FileType fileType)
+ {
+ FREE_IMAGE_FORMAT fif;
+ if (_fileTypeToFreeImage.TryGetValue(fileType, out fif))
+ {
+ return fif;
+ }
+ else
+ {
+ throw new NotImplementedException(
+ "No FREE_IMAGE_FORMAT match for " + fileType.ToString());
+ }
+ }
+ */
+ #endregion
+
+ #region Private fields
+
+ private Exporter _exporter;
+ private int _numTotal;
+ private ExportFileName _batchFileName;
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/Export/ExportFileName.cs b/XLToolbox/Export/ExportFileName.cs
index 56ac1038..19a6329a 100755
--- a/XLToolbox/Export/ExportFileName.cs
+++ b/XLToolbox/Export/ExportFileName.cs
@@ -72,10 +72,10 @@ public ExportFileName(string directory, string template, FileType fileType)
/// internal counter.
///
///
- public string GenerateNext(dynamic worksheet)
+ public string GenerateNext(dynamic sheet)
{
- CurrentWorkbookName = worksheet.Parent.Name;
- CurrentWorksheetName = worksheet.Name;
+ CurrentWorkbookName = sheet.Parent.Name;
+ CurrentWorksheetName = sheet.Name;
Counter++;
string s = _regex.Replace(Template, SubstituteVariable);
// If no index placeholder exists in the template, add the index at the end.
diff --git a/XLToolbox/Export/Exporter.cs b/XLToolbox/Export/Exporter.cs
index b811067f..cca4b19d 100755
--- a/XLToolbox/Export/Exporter.cs
+++ b/XLToolbox/Export/Exporter.cs
@@ -36,7 +36,16 @@ public class Exporter : Bovender.Mvvm.Models.ProcessModel, IDisposable
{
#region Properties
- public bool IsProcessing { get; private set; }
+ public string FileName { get; set; }
+
+ ///
+ /// Gets or sets whether to do a quick export or not.
+ /// Quick export means that the selection is exported
+ /// at the original size.
+ ///
+ public bool QuickExport { get; set; }
+
+ public Preset Preset { get; set; }
public int PercentCompleted
{
@@ -44,7 +53,7 @@ public int PercentCompleted
{
if (_tiledBitmap != null)
{
- return _tiledBitmap.PercentCompleted * 80 / 100 + _percentCompleted;
+ return _tiledBitmap.PercentCompleted * 50 / 100 + _percentCompleted;
}
else
{
@@ -62,149 +71,77 @@ public int PercentCompleted
#region Public methods
- ///
- /// Performs a quick export using a given Preset, but
- /// without altering the size of the current selection:
- /// The dimension properties of the SingleExportSettings
- /// object that defines the operation are ignored.
- ///
- ///
- public void ExportSelectionQuick(SingleExportSettings settings)
+ public override bool Execute()
{
- Logger.Info("ExportSelectionQuick");
- ExportSelection(settings.Preset, settings.FileName);
- }
-
- ///
- /// Exports the current selection from Excel to a graphics file
- /// using the parameters defined in
- ///
- /// Parameters for the graphic export.
- /// Target file name.
- public void ExportSelection(SingleExportSettings settings)
- {
- Logger.Info("ExportSelection");
- if (settings == null)
+ if (Preset == null)
{
- Logger.Fatal("SingleExportSettings is null");
- throw new ArgumentNullException("settings",
- "Must have SingleExportSettings object for the export.");
+ throw new InvalidOperationException("Cannot export because no Preset was given");
}
- double w = settings.Unit.ConvertTo(settings.Width, Unit.Point);
- double h = settings.Unit.ConvertTo(settings.Height, Unit.Point);
- IsProcessing = true;
- Task t = new Task(() =>
+ if (String.IsNullOrWhiteSpace(FileName) && _settings != null)
{
- Logger.Info("Beginning export task");
- try
- {
- ExportSelection(settings.Preset, w, h, settings.FileName);
- IsProcessing = false;
- if (!_cancelled) OnProcessSucceeded();
- }
- catch (Exception e)
- {
- IsProcessing = false;
- Logger.Warn("Exception occurred, raising ExportFailed event");
- Logger.Warn(e);
- OnProcessFailed(e);
- }
- finally
- {
- Logger.Info("Export task finished");
- }
- });
- t.Start();
- }
-
- ///
- /// Starts a batch export of charts and/or drawing objects
- /// (shapes) asynchronously. Callers should subscribe to the
- /// and
- /// events to learn about status changes. The operation can
- /// be cancelled by caling the
- /// method.
- ///
- /// Settings describing the desired operation.
- public void ExportBatchAsync(BatchExportSettings settings)
- {
- Logger.Info("ExportBatchAsync");
- if (IsProcessing)
+ FileName = _settings.FileName;
+ }
+ if (String.IsNullOrWhiteSpace(FileName))
{
- Logger.Warn("Cannot respawn, already running");
- throw new InvalidOperationException(
- "Cannot start batch export while an operation is in progress.");
+ throw new InvalidOperationException("Cannot export because no file name was given");
}
-
- Task t = new Task(() =>
+ bool result = false;
+ double width;
+ double height;
+ if (QuickExport)
{
- IsProcessing = true;
- try
- {
- Instance.Default.DisableScreenUpdating();
- switch (_batchSettings.Scope)
- {
- case BatchExportScope.ActiveSheet:
- _numTotal = CountInSheet(Instance.Default.Application.ActiveSheet);
- ExportSheet(Instance.Default.Application.ActiveSheet);
- break;
- case BatchExportScope.ActiveWorkbook:
- _numTotal = CountInWorkbook(Instance.Default.ActiveWorkbook);
- ExportWorkbook(Instance.Default.ActiveWorkbook);
- break;
- case BatchExportScope.OpenWorkbooks:
- _numTotal = CountInAllWorkbooks();
- ExportAllWorkbooks();
- break;
- default:
- throw new NotImplementedException(String.Format(
- "Batch export not implemented for {0}",
- settings.Scope));
- }
- IsProcessing = false;
- Logger.Info("Finish async task");
- if (!_cancelled) OnProcessSucceeded();
- }
- catch (Exception e)
- {
- IsProcessing = false;
- OnProcessFailed(e);
- }
- finally
+ if (SelectionViewModel.Selection == null)
{
- IsProcessing = false;
- Instance.Default.EnableScreenUpdating();
+ Logger.Fatal("ExportAtOriginalSize: No selection!");
+ throw new InvalidOperationException("Cannot export because nothing is selected in Excel");
}
- });
-
- _batchSettings = settings;
- _cancelled = false;
- _batchFileName = new ExportFileName(settings.Path, settings.FileName,
- settings.Preset.FileType);
- Logger.Info("Start asynchronous export");
- t.Start();
- }
-
- ///
- /// Cancels a running export.
- ///
- public void CancelExport()
- {
- if (IsProcessing)
+ width = SelectionViewModel.Bounds.Width;
+ height = SelectionViewModel.Bounds.Height;
+ }
+ else
{
- _cancelled = true;
- if (_tiledBitmap != null)
+ if (_settings == null)
{
- _tiledBitmap.Cancel();
+ Logger.Fatal("ExportAtOriginalSize: No export settings!");
+ throw new InvalidOperationException("Cannot export because no export settings were given; want to perform quick export?");
}
+ width = _settings.Unit.ConvertTo(_settings.Width, Unit.Point);
+ height = _settings.Unit.ConvertTo(_settings.Height, Unit.Point);
}
+ ExportWithDimensions(width, height);
+ return result;
}
#endregion
- #region Constructor and disposing
+ #region Constructors
+
+ public Exporter(SingleExportSettings settings)
+ : this()
+ {
+ _settings = settings;
+ if (_settings != null)
+ {
+ Preset = _settings.Preset;
+ }
+ }
+
+ public Exporter(SingleExportSettings settings, bool quickExport)
+ : this(settings)
+ {
+ QuickExport = quickExport;
+ }
+
+ public Exporter(Preset preset)
+ : this()
+ {
+ // Without SingleExportSettings, we can only perform a quick export
+ QuickExport = true;
+ Preset = preset;
+ }
- public Exporter()
+ protected Exporter()
+ : base()
{
_dllManager = new DllManager();
_dllManager.LoadDll("freeimage.dll");
@@ -215,13 +152,9 @@ public Exporter()
};
}
- /*
- public Exporter(Preset preset)
- : this()
- {
- Preset = preset;
- }
- * */
+ #endregion
+
+ #region Disposing
~Exporter()
{
@@ -236,34 +169,24 @@ public void Dispose()
protected void Dispose(bool calledFromDispose)
{
- if (calledFromDispose && !_disposed)
+ if (!_disposed)
{
- _dllManager.UnloadDll("freeimage.dll");
+ if (calledFromDispose)
+ {
+ // Free managed resources
+ _dllManager.UnloadDll("freeimage.dll");
+ if (_tiledBitmap != null)
+ {
+ _tiledBitmap.Dispose();
+ }
+ }
_disposed = true;
}
}
#endregion
- #region Private export methods
-
- ///
- /// Performs the actual graphic export with the dimensions of
- /// the current selection.
- ///
- /// Export preset to use.
- /// File name of target file.
- private void ExportSelection(Preset preset, string fileName)
- {
- Logger.Info("ExportSelection(preset, fileName");
- SelectionViewModel svm = new SelectionViewModel(Instance.Default.Application);
- if (svm.Selection == null)
- {
- Logger.Warn("No selection");
- throw new InvalidOperationException("Nothing selected in Excel.");
- }
- ExportSelection(preset, svm.Bounds.Width, svm.Bounds.Height, fileName);
- }
+ #region Private methods
///
/// Performs the actual export for a given selection. This method is
@@ -273,13 +196,16 @@ private void ExportSelection(Preset preset, string fileName)
/// Width of the output graphic.
/// Height of the output graphic.
/// Destination filename (must contain placeholders).
- private void ExportSelection(Preset preset, double widthInPoints, double heightInPoints,
- string fileName)
+ private void ExportWithDimensions(double widthInPoints, double heightInPoints)
{
- Logger.Info("ExportSelection(preset, widthInPoints, heightInPoints, filename)");
+ if (Preset == null)
+ {
+ Logger.Fatal("ExportWithDimensions: No export preset!");
+ throw new InvalidOperationException("Cannot export without export preset");
+ }
+ Logger.Info("ExportWithDimensions");
// Copy current selection to clipboard
- SelectionViewModel svm = new SelectionViewModel(Instance.Default.Application);
- svm.CopyToClipboard();
+ SelectionViewModel.CopyToClipboard();
// Get a metafile view of the clipboard content
// Must not dispose the WorkingClipboard instance before the metafile
@@ -289,321 +215,99 @@ private void ExportSelection(Preset preset, double widthInPoints, double heightI
{
Logger.Info("Get metafile");
emf = clipboard.GetMetafile();
- switch (preset.FileType)
+ switch (Preset.FileType)
{
case FileType.Emf:
- ExportEmf(emf, fileName);
+ ExportEmf(emf);
break;
case FileType.Png:
case FileType.Tiff:
- ExportViaFreeImage(emf, preset, widthInPoints, heightInPoints, fileName);
+ ExportViaFreeImage(emf, widthInPoints, heightInPoints);
break;
default:
throw new NotImplementedException(String.Format(
- "No export implementation for {0}.", preset.FileType));
+ "No export implementation for {0}.", Preset.FileType));
}
}
}
- private void ExportViaFreeImage(Metafile metafile,
- Preset preset, double width, double height, string fileName)
+ private void ExportViaFreeImage(Metafile metafile, double width, double height)
{
Logger.Info("ExportViaFreeImage");
- Logger.Info("Preset: {0}", preset);
+ Logger.Info("Preset: {0}", Preset);
Logger.Info("Width: {0}; height: {1}", width, height);
// Calculate the number of pixels needed for the requested
// output size and resolution; size is given in points (1/72 in),
// resolution is given in dpi.
- int px = (int)Math.Round(width / 72 * preset.Dpi);
- int py = (int)Math.Round(height / 72 * preset.Dpi);
+ int px = (int)Math.Round(width / 72 * Preset.Dpi);
+ int py = (int)Math.Round(height / 72 * Preset.Dpi);
Logger.Info("Pixels: x: {0}; y: {1}", px, py);
-
+ Cancelling += Exporter_Cancelling;
+ PercentCompleted = 10;
_tiledBitmap = new TiledBitmap(px, py);
- PercentCompleted = 25;
- FreeImageBitmap fib = _tiledBitmap.CreateFreeImageBitmap(metafile, preset.Transparency);
+ FreeImageBitmap fib = _tiledBitmap.CreateFreeImageBitmap(metafile, Preset.Transparency);
+ ConvertColor(fib);
+ fib.SetResolution(Preset.Dpi, Preset.Dpi);
+ fib.Comment = Versioning.SemanticVersion.BrandName;
+ PercentCompleted = 30;
+ Logger.Info("Saving {0} file", Preset.FileType);
+ fib.Save(
+ FileName,
+ Preset.FileType.ToFreeImageFormat(),
+ GetSaveFlags()
+ );
+ Cancelling -= Exporter_Cancelling;
+ PercentCompleted = 50;
+ }
- PercentCompleted = 70;
- if (preset.UseColorProfile)
+ private void ConvertColor(FreeImageBitmap freeImageBitmap)
+ {
+ if (Preset.UseColorProfile)
{
- ConvertColorCms(preset, fib);
+ Logger.Info("ConvertColorCms: Convert color using profile");
+ ViewModels.ColorProfileViewModel targetProfile =
+ ViewModels.ColorProfileViewModel.CreateFromName(Preset.ColorProfile);
+ targetProfile.TransformFromStandardProfile(freeImageBitmap);
+ freeImageBitmap.ConvertColorDepth(Preset.ColorSpace.ToFreeImageColorDepth());
}
else
{
- ConvertColor(preset, fib);
+ Logger.Info("ConvertColor: Convert color without profile");
+ freeImageBitmap.ConvertColorDepth(Preset.ColorSpace.ToFreeImageColorDepth());
}
-
- PercentCompleted = 85;
- if (preset.ColorSpace == ColorSpace.Monochrome)
+ if (Preset.ColorSpace == ColorSpace.Monochrome)
{
- SetMonochromePalette(fib);
+ SetMonochromePalette(freeImageBitmap);
}
-
- fib.SetResolution(preset.Dpi, preset.Dpi);
- fib.Comment = Versioning.SemanticVersion.BrandName;
- Logger.Info("Saving {0} file", preset.FileType);
- PercentCompleted = 85;
- fib.Save(
- fileName,
- preset.FileType.ToFreeImageFormat(),
- GetSaveFlags(preset)
- );
- PercentCompleted = 100;
- }
-
- private void ConvertColorCms(Preset preset, FreeImageBitmap freeImageBitmap)
- {
- Logger.Info("Convert color using profile");
- ViewModels.ColorProfileViewModel targetProfile =
- ViewModels.ColorProfileViewModel.CreateFromName(preset.ColorProfile);
- targetProfile.TransformFromStandardProfile(freeImageBitmap);
- freeImageBitmap.ConvertColorDepth(preset.ColorSpace.ToFreeImageColorDepth());
- }
-
- private void ConvertColor(Preset preset, FreeImageBitmap freeImageBitmap)
- {
- Logger.Info("Convert color without profile");
- freeImageBitmap.ConvertColorDepth(preset.ColorSpace.ToFreeImageColorDepth());
}
private void SetMonochromePalette(FreeImageBitmap freeImageBitmap)
{
- Logger.Info("Convert to monochrome");
+ Logger.Info("SetMonochromePalette: Convert to monochrome");
freeImageBitmap.Palette.SetValue(new RGBQUAD(Color.Black), 0);
freeImageBitmap.Palette.SetValue(new RGBQUAD(Color.White), 1);
}
- private void ExportEmf(Metafile metafile, string fileName)
+ private void ExportEmf(Metafile metafile)
{
+ Logger.Info("ExportEmf: exporting...");
IntPtr handle = metafile.GetHenhmetafile();
PercentCompleted = 50;
Logger.Info("ExportEmf, handle: {0}", handle);
- Bovender.Unmanaged.Pinvoke.CopyEnhMetaFile(handle, fileName);
+ Bovender.Unmanaged.Pinvoke.CopyEnhMetaFile(handle, FileName);
PercentCompleted = 100;
}
- private void ExportAllWorkbooks()
- {
- foreach (Workbook wb in Instance.Default.Application.Workbooks)
- {
- ExportWorkbook(wb);
- if (_cancelled) break;
- }
- }
-
- private void ExportWorkbook(Workbook workbook)
+ private FREE_IMAGE_SAVE_FLAGS GetSaveFlags()
{
- ComputeBatchProgress();
- ((_Workbook)workbook).Activate();
- foreach (dynamic ws in workbook.Sheets)
- {
- ExportSheet(ws);
- if (_cancelled) break;
- }
- }
-
- private void ExportSheet(dynamic sheet)
- {
- ComputeBatchProgress();
- sheet.Activate();
- switch (_batchSettings.Layout)
- {
- case BatchExportLayout.SheetLayout:
- ExportSheetLayout(sheet);
- break;
- case BatchExportLayout.SingleItems:
- ExportSheetItems(sheet);
- break;
- default:
- throw new NotImplementedException(
- String.Format("Export of {0} not implemented.", _batchSettings.Layout)
- );
- }
- }
-
- private void ExportSheetLayout(dynamic sheet)
- {
- SheetViewModel svm = new SheetViewModel(sheet);
- switch (_batchSettings.Objects)
- {
- case BatchExportObjects.Charts:
- svm.SelectCharts();
- break;
- case BatchExportObjects.ChartsAndShapes:
- svm.SelectShapes();
- break;
- default:
- throw new NotImplementedException(_batchSettings.Objects.ToString());
- }
- ExportSelection(
- _batchSettings.Preset,
- _batchFileName.GenerateNext(sheet)
- );
- ComputeBatchProgress();
- }
-
- private void ExportSheetItems(dynamic sheet)
- {
- SheetViewModel svm = new SheetViewModel(sheet);
- if (svm.IsChart)
- {
- svm.SelectCharts();
- ExportSelection(
- _batchSettings.Preset,
- _batchFileName.GenerateNext(sheet)
- );
- }
- else
- {
- switch (_batchSettings.Objects)
- {
- case BatchExportObjects.Charts:
- ExportSheetChartItems(svm.Worksheet);
- break;
- case BatchExportObjects.ChartsAndShapes:
- ExportSheetAllItems(svm.Worksheet);
- break;
- default:
- throw new NotImplementedException(
- "Single-item export not implemented for " + _batchSettings.Objects.ToString());
- }
- }
- ComputeBatchProgress();
- }
-
- private void ExportSheetChartItems(Worksheet worksheet)
- {
- // Must use an index-based for loop here.
- // A foreach loop caused lots of 0x800a03ec errors from Excel
- // (for whatever reason).
- ChartObjects cos = worksheet.ChartObjects();
- for (int i = 1; i <= cos.Count; i++)
- {
- cos.Item(i).Select();
- ExportSelection(_batchSettings.Preset, _batchFileName.GenerateNext(worksheet));
- ComputeBatchProgress();
- if (_cancelled) break;
- }
- }
-
- private void ExportSheetAllItems(Worksheet worksheet)
- {
- foreach (Shape sh in worksheet.Shapes)
- {
- sh.Select(true);
- ExportSelection(_batchSettings.Preset, _batchFileName.GenerateNext(worksheet));
- ComputeBatchProgress();
- if (_cancelled) break;
- }
- }
-
- #endregion
-
- #region Private counting methods
-
- private int CountInAllWorkbooks()
- {
- int n = 0;
- foreach (Workbook wb in Instance.Default.Application.Workbooks)
- {
- n += CountInWorkbook(wb);
- }
- return n;
- }
-
- private int CountInWorkbook(Workbook workbook)
- {
- int n = 0;
- foreach (Worksheet ws in workbook.Worksheets)
- {
- n += CountInSheet(ws);
- }
- return n;
- }
-
- private int CountInSheet(dynamic worksheet)
- {
- switch (_batchSettings.Layout)
- {
- case BatchExportLayout.SheetLayout:
- return CountInSheetLayout(worksheet);
- case BatchExportLayout.SingleItems:
- return CountInSheetItems(worksheet);
- default:
- throw new NotImplementedException(
- String.Format("Export of {0} not implemented.", _batchSettings.Layout)
- );
- }
- }
-
- ///
- /// Returns 1 if the contains at least
- /// one chart or drawing object, since all charts/drawing objects will
- /// be exported together into one file.
- ///
- /// Worksheet to examine.
- /// 1 if sheet contains charts/drawings, 0 if not.
- private int CountInSheetLayout(dynamic worksheet)
- {
- SheetViewModel svm = new SheetViewModel(worksheet);
- switch (_batchSettings.Objects)
- {
- case BatchExportObjects.Charts:
- return svm.CountCharts() > 0 ? 1 : 0;
- case BatchExportObjects.ChartsAndShapes:
- return svm.CountShapes() > 0 ? 1 : 0;
- default:
- throw new NotImplementedException(String.Format(
- "Export of {0} not implemented.", _batchSettings.Objects));
- }
- }
-
- private int CountInSheetItems(dynamic worksheet)
- {
- SheetViewModel svm = new SheetViewModel(worksheet);
- switch (_batchSettings.Objects)
- {
- case BatchExportObjects.Charts:
- return svm.CountCharts();
- case BatchExportObjects.ChartsAndShapes:
- return svm.CountShapes();
- default:
- throw new NotImplementedException(String.Format(
- "Export of {0} not implemented.", _batchSettings.Objects));
- }
- }
-
- /*private FREE_IMAGE_FORMAT FileTypeToFreeImage(FileType fileType)
- {
- FREE_IMAGE_FORMAT fif;
- if (_fileTypeToFreeImage.TryGetValue(fileType, out fif))
- {
- return fif;
- }
- else
- {
- throw new NotImplementedException(
- "No FREE_IMAGE_FORMAT match for " + fileType.ToString());
- }
- }
- */
- #endregion
-
- #region Private helper methods
-
- private void ComputeBatchProgress()
- {
- PercentCompleted = Convert.ToInt32(100d * _batchFileName.Counter / _numTotal);
- }
-
- private FREE_IMAGE_SAVE_FLAGS GetSaveFlags(Preset preset)
- {
- switch (preset.FileType)
+ Logger.Info("GetSaveFlags");
+ switch (Preset.FileType)
{
case FileType.Png:
return FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_COMPRESSION |
FREE_IMAGE_SAVE_FLAGS.PNG_INTERLACED;
case FileType.Tiff:
- switch (preset.ColorSpace)
+ switch (Preset.ColorSpace)
{
case ColorSpace.Monochrome:
return FREE_IMAGE_SAVE_FLAGS.TIFF_CCITTFAX4;
@@ -617,41 +321,53 @@ private FREE_IMAGE_SAVE_FLAGS GetSaveFlags(Preset preset)
}
}
- /*
- ///
- /// Adds a file extension to the file name if missing.
- ///
- /// File name, possibly without extension.
- /// File name with extension.
- private string SanitizeFileName(Preset preset, string fileName)
+ private void Exporter_Cancelling(object sender, Bovender.Mvvm.Models.ProcessModelEventArgs args)
+ {
+ if (_tiledBitmap != null)
+ {
+ _tiledBitmap.Cancel();
+ }
+ }
+
+ #endregion
+
+ #region Protected properties
+
+ protected SelectionViewModel SelectionViewModel
{
- string extension = preset.FileType.ToFileNameExtension();
- if (!fileName.ToUpper().EndsWith(extension.ToUpper()))
+ get
{
- fileName += extension;
+ if (_selectionViewModel == null)
+ {
+ _selectionViewModel = new SelectionViewModel(Instance.Default.Application);
+ }
+ return _selectionViewModel;
}
- return fileName;
}
- */
#endregion
#region Private fields
private DllManager _dllManager;
+ private SingleExportSettings _settings;
private bool _disposed;
- private BatchExportSettings _batchSettings;
- private ExportFileName _batchFileName;
- private bool _cancelled;
- private int _numTotal;
private Dictionary _fileTypeToFreeImage;
private TiledBitmap _tiledBitmap;
private int _percentCompleted;
+ private SelectionViewModel _selectionViewModel;
#endregion
#region Private constants
#endregion
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
}
}
diff --git a/XLToolbox/Export/QuickExporter.cs b/XLToolbox/Export/QuickExporter.cs
index 1298edce..724c6c99 100755
--- a/XLToolbox/Export/QuickExporter.cs
+++ b/XLToolbox/Export/QuickExporter.cs
@@ -51,8 +51,8 @@ public void ExportSelection()
SingleExportSettings settings = SingleExportSettings.CreateForSelection(preset);
SingleExportSettingsViewModel svm = new SingleExportSettingsViewModel(settings);
svm.ChooseFileNameMessage.Sent += ChooseFileNameMessage_Sent;
- svm.ShowProgressMessage.Sent += Dispatcher.ShowProgressMessage_Sent;
- svm.ProcessFailedMessage.Sent += Dispatcher.ProcessFailedMessage_Sent;
+ svm.ShowProgressMessage.Sent += Dispatcher.Exporter_ShowProgress_Sent;
+ svm.ProcessFinishedMessage.Sent += Dispatcher.Exporter_ProcessFinished_Sent;
if (svm.ChooseFileNameCommand.CanExecute(null))
{
svm.ChooseFileNameCommand.Execute(null);
@@ -72,8 +72,8 @@ public void ExportBatch()
if ((bvm != null) && bvm.ChooseFolderCommand.CanExecute(null))
{
bvm.ChooseFolderMessage.Sent += ChooseFolderMessage_Sent;
- bvm.ShowProgressMessage.Sent += Dispatcher.ShowProgressMessage_Sent;
- bvm.ProcessFailedMessage.Sent += Dispatcher.ProcessFailedMessage_Sent;
+ bvm.ShowProgressMessage.Sent += Dispatcher.Exporter_ShowProgress_Sent;
+ bvm.ProcessFinishedMessage.Sent += Dispatcher.Exporter_ProcessFinished_Sent;
bvm.ChooseFolderCommand.Execute(null);
}
else
@@ -86,8 +86,8 @@ public void ExportBatch()
bvm = new BatchExportSettingsViewModel();
// Do not 'sanitize' the export options, so that the user
// can see the selected, but disabled options.
- bvm.ShowProgressMessage.Sent += Dispatcher.ShowProgressMessage_Sent;
- bvm.ProcessFailedMessage.Sent += Dispatcher.ProcessFailedMessage_Sent;
+ bvm.ShowProgressMessage.Sent += Dispatcher.Exporter_ShowProgress_Sent;
+ bvm.ProcessFinishedMessage.Sent += Dispatcher.Exporter_ProcessFinished_Sent;
bvm.InjectInto().ShowDialog();
}
else
diff --git a/XLToolbox/Export/ViewModels/BatchExportSettingsViewModel.cs b/XLToolbox/Export/ViewModels/BatchExportSettingsViewModel.cs
index f6a1e295..5c2b2a7a 100755
--- a/XLToolbox/Export/ViewModels/BatchExportSettingsViewModel.cs
+++ b/XLToolbox/Export/ViewModels/BatchExportSettingsViewModel.cs
@@ -306,10 +306,14 @@ public BatchExportSettingsViewModel()
{ }
public BatchExportSettingsViewModel(BatchExportSettings settings)
- : base()
+ : this(new BatchExporter(settings as BatchExportSettings))
+ { }
+
+ public BatchExportSettingsViewModel(BatchExporter batchExporter)
+ : base(batchExporter)
{
- Settings = settings;
- PresetViewModels.Select(settings.Preset);
+ Settings = batchExporter.Settings;
+ PresetViewModels.Select(Settings.Preset);
FileName = String.Format("{{{0}}}_{{{1}}}_{{{2}}}",
Strings.Workbook, Strings.Worksheet, Strings.Index);
Scope.PropertyChanged += Scope_PropertyChanged;
@@ -320,8 +324,8 @@ public BatchExportSettingsViewModel(BatchExportSettings settings)
#endregion
- #region Implementation of SettingsViewModelBase
-
+ #region Implementation of abstract methods
+
///
/// Determines the suggested target directory and sends the
/// ChooseFileNameMessage.
@@ -345,6 +349,18 @@ private bool CanChooseFolder()
return CanExport();
}
+ protected override int GetPercentCompleted()
+ {
+ if (Exporter != null)
+ {
+ return Exporter.PercentCompleted;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
protected override void DoExport()
{
Logger.Info("DoExport");
@@ -358,17 +374,9 @@ protected override void DoExport()
protected override bool CanExport()
{
- return CanExecuteMatrix[Scope.AsEnum][Objects.AsEnum][Layout.AsEnum] &&
- (Settings.Preset != null);
- }
-
- #endregion
-
- #region Implementation of ProcessViewModelBase
-
- protected override void Execute()
- {
- Exporter.ExportBatchAsync(Settings as BatchExportSettings);
+ return (Settings != null) &&
+ (Settings.Preset != null) &&
+ CanExecuteMatrix[Scope.AsEnum][Objects.AsEnum][Layout.AsEnum];
}
#endregion
@@ -727,6 +735,15 @@ private ScopeStates CanExecuteMatrix
}
}
+ private BatchExporter Exporter
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ return ProcessModel as BatchExporter;
+ }
+ }
+
#endregion
#region Private fields
diff --git a/XLToolbox/Export/ViewModels/PresetsRepositoryViewModel.cs b/XLToolbox/Export/ViewModels/PresetsRepositoryViewModel.cs
index 8e2fa922..8f886e56 100755
--- a/XLToolbox/Export/ViewModels/PresetsRepositoryViewModel.cs
+++ b/XLToolbox/Export/ViewModels/PresetsRepositoryViewModel.cs
@@ -171,6 +171,11 @@ public void Select(Preset preset)
throw new ArgumentNullException("preset", "Cannot select PresetViewModel without Preset");
}
PresetViewModel pvm = ViewModels.FirstOrDefault(p => p.IsViewModelOf(preset));
+ if (pvm == null)
+ {
+ pvm = new PresetViewModel(preset);
+ ViewModels.Add(pvm);
+ }
pvm.IsSelected = true;
}
diff --git a/XLToolbox/Export/ViewModels/SettingsViewModelBase.cs b/XLToolbox/Export/ViewModels/SettingsViewModelBase.cs
index e39dcf37..e527694c 100755
--- a/XLToolbox/Export/ViewModels/SettingsViewModelBase.cs
+++ b/XLToolbox/Export/ViewModels/SettingsViewModelBase.cs
@@ -90,19 +90,6 @@ public string FileName
protected Settings Settings { get; set; }
- protected Exporter Exporter
- {
- get
- {
- if (_exporter == null)
- {
- _exporter = new Exporter();
- ProcessModel = _exporter; // assigning property hooks up events
- }
- return _exporter;
- }
- }
-
#endregion
#region Commands
@@ -154,8 +141,8 @@ public Message EditPresetsMessage
#region Constructor
- public SettingsViewModelBase()
- : base()
+ public SettingsViewModelBase(Bovender.Mvvm.Models.ProcessModel exporter)
+ : base(exporter)
{ }
#endregion
@@ -228,21 +215,6 @@ public override object RevealModelObject()
return Settings;
}
- protected override bool IsProcessing()
- {
- return Exporter.IsProcessing;
- }
-
- protected override int GetPercentCompleted()
- {
- return Exporter.PercentCompleted;
- }
-
- protected override void CancelProcess()
- {
- Exporter.CancelExport();
- }
-
#endregion
#region Private methods
@@ -263,7 +235,6 @@ private void PresetViewModels_PropertyChanged(object sender, PropertyChangedEven
DelegatingCommand _editPresetsCommand;
Message _editPresetsMessage;
PresetsRepositoryViewModel _presetsRepositoryViewModel;
- Exporter _exporter;
#endregion
diff --git a/XLToolbox/Export/ViewModels/SingleExportSettingsViewModel.cs b/XLToolbox/Export/ViewModels/SingleExportSettingsViewModel.cs
index 60ef622f..de935c75 100755
--- a/XLToolbox/Export/ViewModels/SingleExportSettingsViewModel.cs
+++ b/XLToolbox/Export/ViewModels/SingleExportSettingsViewModel.cs
@@ -24,6 +24,7 @@
using XLToolbox.Export.Models;
using System.Threading;
using System.Threading.Tasks;
+using System.Diagnostics;
namespace XLToolbox.Export.ViewModels
{
@@ -231,7 +232,7 @@ public SingleExportSettingsViewModel()
{ }
public SingleExportSettingsViewModel(SingleExportSettings singleExportSettings)
- : base()
+ : base(new Exporter(singleExportSettings))
{
Settings = singleExportSettings;
PresetViewModels.Select(Settings.Preset);
@@ -249,15 +250,14 @@ public SingleExportSettingsViewModel(SingleExportSettings singleExportSettings)
///
protected override void DoExport()
{
- StartProcess();
- // if (CanExport())
- // {
- // // Logger.Info("DoExport");
- // // SelectedPreset.Store();
- // // UserSettings.UserSettings.Default.ExportUnit = Units.AsEnum;
- // // SaveExportPath();
- // StartProcess();
- // }
+ if (CanExport())
+ {
+ Logger.Info("DoExport");
+ SelectedPreset.Store();
+ UserSettings.UserSettings.Default.ExportUnit = Units.AsEnum;
+ SaveExportPath();
+ StartProcess();
+ }
}
protected override bool CanExport()
@@ -268,15 +268,22 @@ protected override bool CanExport()
(Width > 0) && (Height > 0);
}
- protected override void Execute()
+ protected override bool BeforeStartProcess()
{
Settings.Preset = SelectedPreset.RevealModelObject() as Preset;
- Exporter.ExportSelection(Settings as SingleExportSettings);
+ return base.BeforeStartProcess();
}
protected override int GetPercentCompleted()
{
- return Exporter.PercentCompleted;
+ if (Exporter != null)
+ {
+ return Exporter.PercentCompleted;
+ }
+ else
+ {
+ return 0;
+ }
}
#endregion
@@ -301,6 +308,19 @@ protected override void SaveExportPath()
#endregion
+ #region Private properties
+
+ private Exporter Exporter
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ return ProcessModel as Exporter;
+ }
+ }
+
+ #endregion
+
#region Private methods
private void DoChooseFileName()
diff --git a/XLToolbox/Greeter/GreeterView.xaml b/XLToolbox/Greeter/GreeterView.xaml
index 7de8ac7f..122719a7 100755
--- a/XLToolbox/Greeter/GreeterView.xaml
+++ b/XLToolbox/Greeter/GreeterView.xaml
@@ -19,8 +19,10 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XLToolbox/Greeter/GreeterViewModel.cs b/XLToolbox/Greeter/GreeterViewModel.cs
index d133a974..5c1ab594 100755
--- a/XLToolbox/Greeter/GreeterViewModel.cs
+++ b/XLToolbox/Greeter/GreeterViewModel.cs
@@ -29,20 +29,8 @@ namespace XLToolbox.Greeter
///
/// View model for the greeter screen.
///
- public class GreeterViewModel : ViewModelBase
+ public class GreeterViewModel : About.AboutViewModel
{
- #region Public properties
-
- public SemanticVersion Version
- {
- get
- {
- return XLToolbox.Versioning.SemanticVersion.CurrentVersion();
- }
- }
-
- #endregion
-
#region Commands
public DelegatingCommand WhatsNewCommand
@@ -75,36 +63,6 @@ public DelegatingCommand DonateCommand
#endregion
- /*
- #region MVVM messages
-
- public Message WhatsNewMessage
- {
- get
- {
- if (_whatsNewMessage == null)
- {
- _whatsNewMessage = new Message();
- }
- return _whatsNewMessage;
- }
- }
-
- public Message DonateMessage
- {
- get
- {
- if (_donateMessage == null)
- {
- _donateMessage = new Message();
- }
- return _donateMessage;
- }
- }
-
- #endregion
- */
-
#region Private methods
private void DoShowWhatsNew()
diff --git a/XLToolbox/Legacy/LegacyToolbox.cs b/XLToolbox/Legacy/LegacyToolbox.cs
index a8089594..bcd39d4e 100755
--- a/XLToolbox/Legacy/LegacyToolbox.cs
+++ b/XLToolbox/Legacy/LegacyToolbox.cs
@@ -192,7 +192,7 @@ public void RunCommand(Command command)
app.Run("RunPointChart");
break;
case Command.Watermark:
- app.Run("RuneWatermark");
+ app.Run("RunWatermark");
break;
case Command.LegacyPrefs:
app.Run("RunPreferences");
diff --git a/XLToolbox/Legacy/XLToolboxLegacyAddin.xlam b/XLToolbox/Legacy/XLToolboxLegacyAddin.xlam
index 672b69f6..bdcc5533 100755
Binary files a/XLToolbox/Legacy/XLToolboxLegacyAddin.xlam and b/XLToolbox/Legacy/XLToolboxLegacyAddin.xlam differ
diff --git a/XLToolbox/Logging/IncompleteShutdownLoggingDisabled.xaml b/XLToolbox/Logging/IncompleteShutdownLoggingDisabled.xaml
index 7ca116f2..7f105dfb 100755
--- a/XLToolbox/Logging/IncompleteShutdownLoggingDisabled.xaml
+++ b/XLToolbox/Logging/IncompleteShutdownLoggingDisabled.xaml
@@ -25,7 +25,7 @@
xmlns:bov="clr-namespace:Bovender.Mvvm.Views.Settings;assembly=Bovender"
xmlns:actions="clr-namespace:Bovender.Mvvm.Actions;assembly=Bovender"
bov:WindowState.Save="True" bov:WindowState.CenterScreen="True"
- ResizeMode="NoResize"
+ ResizeMode="NoResize" Topmost="True"
ShowInTaskbar="False" Width="480" SizeToContent="Height"
Title="{x:Static l:Strings.IncompleteShutdown}"
>
diff --git a/XLToolbox/Logging/IncompleteShutdownLoggingEnabled.xaml b/XLToolbox/Logging/IncompleteShutdownLoggingEnabled.xaml
index eaa12670..6c004919 100755
--- a/XLToolbox/Logging/IncompleteShutdownLoggingEnabled.xaml
+++ b/XLToolbox/Logging/IncompleteShutdownLoggingEnabled.xaml
@@ -25,7 +25,7 @@
xmlns:bov="clr-namespace:Bovender.Mvvm.Views.Settings;assembly=Bovender"
xmlns:actions="clr-namespace:Bovender.Mvvm.Actions;assembly=Bovender"
bov:WindowState.Save="True" bov:WindowState.CenterScreen="True"
- ResizeMode="CanResizeWithGrip"
+ ResizeMode="CanResizeWithGrip" Topmost="True"
ShowInTaskbar="False" Width="720" MinWidth="640"
Height="360" MinHeight="320"
Title="{x:Static l:Strings.IncompleteShutdown}"
diff --git a/XLToolbox/Logging/LogFile.cs b/XLToolbox/Logging/LogFile.cs
index b622dcb3..0367145a 100755
--- a/XLToolbox/Logging/LogFile.cs
+++ b/XLToolbox/Logging/LogFile.cs
@@ -30,13 +30,19 @@ namespace XLToolbox.Logging
/// Provides logging to file and to the debug console; wraps
/// NLog configuration and targets.
///
- public class LogFile
+ public class LogFile : Bovender.Logging.LogFile
{
#region Singleton
- public static LogFile Default { get { return _lazy.Value; } }
+ new public static LogFile Default { get { return _lazy.Value; } }
- private static readonly Lazy _lazy = new Lazy(() => new LogFile());
+ private static readonly Lazy _lazy = new Lazy(
+ () =>
+ {
+ LogFile logFile = new LogFile();
+ Bovender.Logging.LogFile.LogFileProvider = new Func(() => logFile);
+ return logFile;
+ });
#endregion
@@ -46,7 +52,7 @@ public class LogFile
/// Gets whether file logging is enabled, without initializing
/// the singleton instance if it isn't.
///
- public static bool IsInitializedAndEnabled
+ new public static bool IsInitializedAndEnabled
{
get
{
@@ -58,32 +64,10 @@ public static bool IsInitializedAndEnabled
#region Properties
- public bool IsFileLoggingEnabled
- {
- get
- {
- return _fileLoggingEnabled;
- }
- set
- {
- if (value != _fileLoggingEnabled)
- {
- if (value)
- {
- EnableFileLogging();
- }
- else
- {
- DisableFileLogging();
- }
- }
- }
- }
-
///
/// Gets the folder where log files are stored.
///
- public string LogFolder
+ public override string LogFolder
{
get
{
@@ -98,161 +82,19 @@ public string LogFolder
}
}
- ///
- /// Gets the complete path and file name of the 'current' log file.
- ///
- public string CurrentLogPath
- {
- get
- {
- if (_currentLogPath == null)
- {
- _currentLogPath = System.IO.Path.Combine(LogFolder, LOG_FILE_NAME);
- }
- return _currentLogPath;
- }
- }
-
- ///
- /// Gets the contents of the current log file. Returns an error
- /// string if the log file could not be read (e.g. if it does not
- /// exist).
- ///
- public string CurrentLog
- {
- get
- {
- try
- {
- return System.IO.File.ReadAllText(CurrentLogPath);
- }
- catch (System.IO.IOException e)
- {
- return e.Message;
- }
- }
- }
-
- ///
- /// Gets whether the 'current' log file is available,
- /// i.e. if the logfile exists. If loggint is disabled,
- /// this file contains the information when file logging
- /// was enabled last.
- ///
- public bool IsCurrentLogAvailable
- {
- get
- {
- return System.IO.File.Exists(CurrentLogPath);
- }
- }
-
#endregion
#region Constructor
private LogFile()
- {
- _config = new LoggingConfiguration();
- LogManager.Configuration = _config;
-
- }
-
- #endregion
-
- #region Public methods
-
- public void ShowFolderInExplorer()
- {
- System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(LogFolder));
- }
-
- public void EnableDebugLogging()
- {
- if (!_debugLogginEnabled)
- {
- _debugLogginEnabled = true;
- DebuggerTarget t = new DebuggerTarget();
- _config.AddTarget(DEBUG_TARGET, t);
- _config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, t));
- LogManager.ReconfigExistingLoggers();
- }
- }
-
- #endregion
-
- #region Protected properties and methods
-
- ///
- /// Gets the complete path and file name layout for the archive files.
- ///
- protected string ArchivedLogsPath
- {
- get
- {
- if (_archivedLogsPath == null)
- {
- _archivedLogsPath = System.IO.Path.Combine(LogFolder, ARCHIVE_FILE_NAME);
- }
- return _archivedLogsPath;
- }
- }
-
- protected void EnableFileLogging()
- {
- _fileLoggingEnabled = true;
- if (_fileTarget == null)
- {
- _fileTarget = new FileTarget();
- _fileTarget.FileName = CurrentLogPath;
- _fileTarget.ArchiveFileName = ArchivedLogsPath;
- _fileTarget.ArchiveNumbering = ArchiveNumberingMode.Date;
- _fileTarget.ArchiveDateFormat = ARCHIVE_DATE_FORMAT;
- _fileTarget.ArchiveEvery = FileArchivePeriod.Day;
- _fileTarget.MaxArchiveFiles = MAX_ARCHIVE_FILES;
- AsyncTargetWrapper wrapper = new AsyncTargetWrapper(_fileTarget);
- _config.AddTarget(FILE_TARGET, wrapper);
- }
- if (_fileRule == null)
- {
- _fileRule = new LoggingRule("*", LogLevel.Info, _fileTarget);
- }
- _config.LoggingRules.Add(_fileRule);
- LogManager.ReconfigExistingLoggers();
- Logger.Info("===== Begin file logging =====");
- }
-
- protected void DisableFileLogging()
- {
- Logger.Info("Disabling file logging");
- _config.LoggingRules.Remove(_fileRule);
- LogManager.ReconfigExistingLoggers();
- _fileLoggingEnabled = false;
- }
+ : base()
+ { }
#endregion
#region Private fields
- private string _logFolder;
- private string _currentLogPath;
- private string _archivedLogsPath;
- private bool _debugLogginEnabled;
- private bool _fileLoggingEnabled;
- private LoggingConfiguration _config;
- private FileTarget _fileTarget;
- private LoggingRule _fileRule;
-
- #endregion
-
- #region Private constants
-
- private const string FILE_TARGET = "file";
- private const string DEBUG_TARGET = "debug";
- private const string LOG_FILE_NAME = "current-log.txt";
- private const string ARCHIVE_FILE_NAME = "log-archived-on-{#}.txt";
- private const string ARCHIVE_DATE_FORMAT = "yyyy-MM-dd";
- private const int MAX_ARCHIVE_FILES = 7;
+ string _logFolder;
#endregion
diff --git a/XLToolbox/Mvvm/Actions/ShowHtmlAction.cs b/XLToolbox/Mvvm/Actions/ShowHtmlAction.cs
index b5f40b04..d417eb4e 100755
--- a/XLToolbox/Mvvm/Actions/ShowHtmlAction.cs
+++ b/XLToolbox/Mvvm/Actions/ShowHtmlAction.cs
@@ -32,13 +32,17 @@ class ShowHtmlAction : StringMessageAction
public string HtmlResource { get; set; }
protected override Window CreateView()
+ {
+ return new HtmlFileView();
+ }
+
+ protected override ViewModelBase GetDataContext(MessageContent messageContent)
{
if (!string.IsNullOrEmpty(HtmlResource))
{
HtmlFileViewModel vm = new HtmlFileViewModel(HtmlResource);
vm.Caption = Caption;
- Window view = vm.InjectInto();
- return view;
+ return vm;
}
else
{
diff --git a/XLToolbox/Mvvm/Views/StringMessageContentView.xaml b/XLToolbox/Mvvm/Views/StringMessageContentView.xaml
index 8ad423b6..90a18dad 100755
--- a/XLToolbox/Mvvm/Views/StringMessageContentView.xaml
+++ b/XLToolbox/Mvvm/Views/StringMessageContentView.xaml
@@ -32,13 +32,13 @@
-
-
-
diff --git a/XLToolbox/Properties/AssemblyInfo.cs b/XLToolbox/Properties/AssemblyInfo.cs
index a55cdc2e..1837a4ea 100755
--- a/XLToolbox/Properties/AssemblyInfo.cs
+++ b/XLToolbox/Properties/AssemblyInfo.cs
@@ -49,5 +49,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("7.0.0.26")]
-[assembly: AssemblyFileVersion("7.0.0.26")]
+[assembly: AssemblyVersion("7.0.0.27")]
+[assembly: AssemblyFileVersion("7.0.0.27")]
diff --git a/XLToolbox/Properties/Settings.Designer.cs b/XLToolbox/Properties/Settings.Designer.cs
index 6f8b10f4..c415a56f 100755
--- a/XLToolbox/Properties/Settings.Designer.cs
+++ b/XLToolbox/Properties/Settings.Designer.cs
@@ -115,11 +115,20 @@ public string KeyboardShortcutsUrl {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("Daniel\'s XL Toolbox")]
+ [global::System.Configuration.DefaultSettingValueAttribute("XLToolbox")]
public string AppDataFolder {
get {
return ((string)(this["AppDataFolder"]));
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("700")]
+ public int WorkbookMonitorIntervalMilliseconds {
+ get {
+ return ((int)(this["WorkbookMonitorIntervalMilliseconds"]));
+ }
+ }
}
}
diff --git a/XLToolbox/Properties/Settings.settings b/XLToolbox/Properties/Settings.settings
index c62cfbf2..df069100 100755
--- a/XLToolbox/Properties/Settings.settings
+++ b/XLToolbox/Properties/Settings.settings
@@ -33,7 +33,10 @@
https://msdn.microsoft.com/en-us/library/office/ff197461.aspx#Anchor_1
- Daniel's XL Toolbox
+ XLToolbox
+
+
+ 700
\ No newline at end of file
diff --git a/XLToolbox/Resources/html/credits.html b/XLToolbox/Resources/html/credits.html
old mode 100755
new mode 100644
index f293d9cf..6c27fb51
--- a/XLToolbox/Resources/html/credits.html
+++ b/XLToolbox/Resources/html/credits.html
@@ -1,4 +1,4 @@
-
+
@@ -14,30 +14,30 @@
Credits
-
This open-source project is hosted by Sourceforge.net.
-
The installer was built with InnoSetup by Jordan Russell.
+
This open-source project is hosted on GitHub. For many years, the hosting provider was Sourceforge.net, where the source code (and downloads) for legacy versions can still be found.
+
The installer was built with InnoSetup by Jordan Russell using my own VstoAddinInstaller scripts..
Third-party code libraries
-
This software uses two free libraries:
+
This software uses free libraries:
-
FreeImage: Image handling library. FreeImage is used under the GNU GPL v. 2. The 64-bit DLL file was compiled by Daniel Kraus.
-
LittleCMS: Color management system. LittleCMS is used under the MIT (aka Expat) license.
+
FreeImage: Image handling library. FreeImage is used under the GNU GPL v. 3. The 64-bit DLL file was compiled by Daniel Kraus.
+
LittleCMS: Color management system.
+LittleCMS is used under the MIT (aka Expat) license.
+
NLog: Provides technical logging (logging must be turned on explicitly if needed to troubleshoot issues). NLog is used under the terms of the BSD license.
Algorithms
The API error message procedure (used for the Auto Backup function) was written by Chip Pearson (www.cpearson.com) and is in the public domain.
Some programming concepts were inspired by John Walkenbach's "Power Programming for Excel® 2003 VBA", and "Professional Excel Development" by Stephen Bullen, Rob Bovey, and John Green.
Some routines are taken from the book "Professional Excel Development" by Stephen Bullen, Rob Bovey, and John Green, with kind permission.
-
This program incorporates a StackOverflow answer by Tomas Kafka, used under CC BY-SA 3.0.
The KLD algorithm for group allocation is a modification of a published algorithm that I developed further. The original algorithm was published by Endo et al. in Contemporary Clinical Trials 27 (2006) 420-431, doi:10.1016/j.cct.2006.05.002.
The algorithm to compute a p value from a q statistic (the studentized range) was ported from Fortran to C++ by Daniel Kraus. The original algorithm has been published as algorithm no. 190 by the Royal Statistical Society.
Website
-
This website's layout is based on the Gumby 2 framework. Pages are compiled using nanoc. The donation page uses jQuery and jQueryUI, both under the MIT license.
-
The Ubuntu Font is used under the Ubuntu Font License, version 1.0.
-
The check mark symbol was designed by Arne Nordmann and is in the public domain.
+
This website's layout is based on the Bootstrap 3 framework, with Glyphicons. Pages are compiled using nanoc. The donation page uses jQuery and jQueryUI, both under the MIT license.
+
This site uses Shariff as social media sharing technology.
+
The check mark symbol was designed by Arne Nordmann and is in the public domain.
The time trial icon was made by Maxxli2 and is in the public domain.
The talk sign was made by Eugenio Hansen, and AnonMoos, and and is in the public domain.
The book icon was made by Pluke, Doodledoo, and Palosirkka, and is licensed under the GLPL.
The logo on the translations page was made by Stannered, DanniDF1995, Mozaika2, LMFAO, and Palosirkka, and is licensed under the GLPL.
The following may be trademarks or registered trademarks of Microsoft® Corporation: Windows, Windows XP, Windows Vista, Vista, Excel®, Office, Visual Basic, and Visual Basic For Applications. Any trademarks that appear on this site are the property of their respective owners.
diff --git a/XLToolbox/SheetManager/SheetManagerEventArgs.cs b/XLToolbox/SheetManager/SheetManagerEventArgs.cs
index c9a29658..8024b142 100755
--- a/XLToolbox/SheetManager/SheetManagerEventArgs.cs
+++ b/XLToolbox/SheetManager/SheetManagerEventArgs.cs
@@ -24,11 +24,11 @@ namespace XLToolbox.SheetManager
{
public class SheetManagerEventArgs : EventArgs
{
- public SheetManagerPane Instance { get; private set; }
+ public SheetManagerTaskPane TaskPane { get; private set; }
- public SheetManagerEventArgs(SheetManagerPane instance)
+ public SheetManagerEventArgs(SheetManagerTaskPane sheetManagerTaskPane)
{
- Instance = instance;
+ TaskPane = sheetManagerTaskPane;
}
}
}
diff --git a/XLToolbox/SheetManager/SheetManagerPane.cs b/XLToolbox/SheetManager/SheetManagerPane.cs
deleted file mode 100755
index 13932997..00000000
--- a/XLToolbox/SheetManager/SheetManagerPane.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-using Microsoft.Office.Tools;
-/* SheetManagerPane.cs
- * part of Daniel's XL Toolbox NG
- *
- * Copyright 2014-2016 Daniel Kraus
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-using System.Windows.Forms.Integration;
-using XLToolbox.Excel.ViewModels;
-
-namespace XLToolbox.SheetManager
-{
- ///
- /// Singleton class that handles the Worksheet Manager task pane.
- ///
- public class SheetManagerPane
- {
- #region Singleton factory
-
- public static SheetManagerPane Default
- {
- get
- {
- return _lazy.Value;
- }
- }
-
- ///
- /// Gets whether the sheet manager task pane has been initialized and
- /// visible. Other than accessing the Default.Visible property, this
- /// method won't cause the singleton to be instantiated.
- ///
- public static bool InitializedAndVisible
- {
- get
- {
- if (_lazy.IsValueCreated)
- {
- return Default.Visible;
- }
- else
- {
- return false;
- }
- }
- }
-
- #endregion
-
- #region Public properties
-
- public bool Visible
- {
- get
- {
- return _pane.Visible;
- }
- set
- {
- _pane.Visible = value;
- }
- }
-
- public int Width
- {
- get
- {
- return _pane.Width;
- }
- set
- {
- _pane.Width = value;
- }
- }
-
- #endregion
-
- #region Events
-
- ///
- /// Raised when the sheet manager singleton has been initialized.
- /// Caveat: At the time when the event is raised, the static Default
- /// property will not yet return the instance. Subscribers to this
- /// event should use the SheetManagerEventArgs.Instance property
- /// to access the singleton instance.
- ///
- ///
- /// This is a static event. Subscribers should take care to unsubscribe
- /// from it, otherwise they will never be garbage-collected.
- ///
- public static event EventHandler SheetManagerInitialized;
-
- ///
- /// Raised when the visibility of the encapsulated task pane changed.
- ///
- public event EventHandler VisibilityChanged;
-
- #endregion
-
- #region Constructor
-
- private SheetManagerPane()
- {
- CreateTaskPane();
- }
-
- #endregion
-
- #region Private methods
-
- private static void OnInitialized(SheetManagerPane sheetManagerPane)
- {
- EventHandler h = SheetManagerInitialized;
- if (h != null)
- {
- h(null, new SheetManagerEventArgs(sheetManagerPane));
- }
- }
-
- private void OnVisibilityChanged()
- {
- UserSettings.UserSettings.Default.SheetManagerVisible = _pane.Visible;
- if (_pane.Visible)
- {
- _viewModel.MonitorWorkbook.Execute(null);
- }
- else
- {
- _viewModel.UnmonitorWorkbook.Execute(null);
- }
- EventHandler h = VisibilityChanged;
- if (h != null)
- {
- h(this, new SheetManagerEventArgs(this));
- }
- }
-
- private void CreateTaskPane()
- {
- _viewModel = new WorkbookViewModel(Instance.Default.ActiveWorkbook);
- UserControl userControl = new UserControl();
- SheetManagerControl view = new SheetManagerControl() { DataContext = _viewModel };
- ElementHost elementHost = new ElementHost() { Child = view };
- userControl.Controls.Add(elementHost);
- elementHost.Dock = DockStyle.Fill;
- _pane = Globals.CustomTaskPanes.Add(userControl, Strings.WorksheetManager);
- _pane.Width = UserSettings.UserSettings.Default.TaskPaneWidth;
- _pane.VisibleChanged += (sender, args) =>
- {
- OnVisibilityChanged();
- };
- }
-
- #endregion
-
- #region Private fields
-
- private WorkbookViewModel _viewModel;
- private CustomTaskPane _pane;
-
- #endregion
-
- #region Private static fields
-
- private static Lazy _lazy = new Lazy(
- () =>
- {
- SheetManagerPane p = new SheetManagerPane();
- OnInitialized(p);
- return p;
- }
- );
-
- #endregion
- }
-}
diff --git a/XLToolbox/SheetManager/SheetManagerTaskPane.cs b/XLToolbox/SheetManager/SheetManagerTaskPane.cs
new file mode 100755
index 00000000..fe3db717
--- /dev/null
+++ b/XLToolbox/SheetManager/SheetManagerTaskPane.cs
@@ -0,0 +1,183 @@
+using Microsoft.Office.Tools;
+/* SheetManagerTaskPane.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.Integration;
+using XLToolbox.Excel.ViewModels;
+
+namespace XLToolbox.SheetManager
+{
+ public class SheetManagerTaskPane
+ {
+ #region Public properties
+
+ public WorkbookViewModel ViewModel { get; private set; }
+
+ public int Width
+ {
+ get
+ {
+ if (_pane != null)
+ {
+ return _pane.Width;
+ }
+ else
+ {
+ throw new InvalidOperationException("Custom task pane not initialized");
+ }
+ }
+ set
+ {
+ if (_pane != null)
+ {
+ _pane.Width = value;
+ _width = value;
+ }
+ else
+ {
+ throw new InvalidOperationException("Custom task pane not initialized");
+ }
+ }
+ }
+
+ public bool Visible
+ {
+ get
+ {
+ if (_pane != null)
+ {
+ return _pane.Visible;
+ }
+ else
+ {
+ throw new InvalidOperationException("Custom task pane not initialized");
+ }
+ }
+ set
+ {
+ if (_pane != null)
+ {
+ if (value != _visible)
+ {
+ _pane.Visible = value;
+ _visible = value;
+ OnVisibilityChanged();
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException("Custom task pane not initialized");
+ }
+ }
+ }
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler VisibilityChanged;
+
+ #endregion
+
+ #region Constructor
+
+ public SheetManagerTaskPane(WorkbookViewModel workbookViewModel, int initialWidth, bool visible)
+ {
+ if (workbookViewModel == null)
+ {
+ throw new ArgumentNullException("workbookViewModel", "WorkbokViewModel must not be null");
+ }
+ ViewModel = workbookViewModel;
+ _width = initialWidth;
+ _visible = visible;
+ CreateCustomTaskPane();
+ }
+
+ #endregion
+
+ #region Protected methods
+
+ protected void MonitorWorkbook(bool visible)
+ {
+ if (visible)
+ {
+ ViewModel.MonitorWorkbook.Execute(null);
+ }
+ else
+ {
+ ViewModel.UnmonitorWorkbook.Execute(null);
+ }
+ }
+
+ protected virtual void OnVisibilityChanged()
+ {
+ MonitorWorkbook(_visible);
+ EventHandler h = VisibilityChanged;
+ if (h != null)
+ {
+ h(this, new SheetManagerEventArgs(this));
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private void CreateCustomTaskPane()
+ {
+ Logger.Info("CreateCustomTaskPane");
+ UserControl userControl = new UserControl();
+ SheetManagerControl view = new SheetManagerControl() { DataContext = ViewModel };
+ ElementHost elementHost = new ElementHost() { Child = view };
+ userControl.Controls.Add(elementHost);
+ elementHost.Dock = DockStyle.Fill;
+ _pane = Globals.CustomTaskPanes.Add(userControl, Strings.WorksheetManager);
+ _pane.Width = _width;
+ _pane.Visible = _visible;
+ MonitorWorkbook(_visible);
+ _pane.VisibleChanged += (sender, args) =>
+ {
+ _visible = _pane.Visible;
+ OnVisibilityChanged();
+ };
+
+ }
+
+ #endregion
+
+ #region Private fields
+
+ private CustomTaskPane _pane;
+ private bool _visible;
+ private int _width;
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/SheetManager/TaskPaneManager.cs b/XLToolbox/SheetManager/TaskPaneManager.cs
new file mode 100755
index 00000000..a50d3082
--- /dev/null
+++ b/XLToolbox/SheetManager/TaskPaneManager.cs
@@ -0,0 +1,287 @@
+using Microsoft.Office.Tools;
+/* SheetManagerPane.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using XLToolbox.Excel.ViewModels;
+
+namespace XLToolbox.SheetManager
+{
+ ///
+ /// Singleton class that handles the Worksheet Manager task pane.
+ ///
+ public class TaskPaneManager
+ {
+ #region Singleton factory
+
+ public static TaskPaneManager Default
+ {
+ get
+ {
+ return _lazy.Value;
+ }
+ }
+
+ ///
+ /// Gets whether the sheet manager task pane has been initialized and
+ /// visible. Other than accessing the Default.Visible property, this
+ /// method won't cause the singleton to be instantiated.
+ ///
+ public static bool InitializedAndVisible
+ {
+ get
+ {
+ if (_lazy.IsValueCreated)
+ {
+ return Default.Visible;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Public properties
+
+ public bool Visible
+ {
+ get
+ {
+ return _visible;
+ }
+ set
+ {
+ Logger.Info("Visible: Set: {0}", value);
+ _visible = value;
+ foreach (SheetManagerTaskPane pane in Panes.Values)
+ {
+ pane.Visible = value;
+ }
+ }
+ }
+
+ public int Width
+ {
+ get
+ {
+ return _width;
+ }
+ set
+ {
+ Logger.Info("Width: Set: {0}", value);
+ _width = value;
+ foreach (SheetManagerTaskPane pane in Panes.Values)
+ {
+ pane.Width = value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Raised when the sheet manager singleton has been initialized.
+ /// Caveat: At the time when the event is raised, the static Default
+ /// property will not yet return the instance. Subscribers to this
+ /// event should use the SheetManagerEventArgs.Instance property
+ /// to access the singleton instance.
+ ///
+ ///
+ /// This is a static event. Subscribers should take care to unsubscribe
+ /// from it, otherwise they will never be garbage-collected.
+ ///
+ public static event EventHandler Initialized;
+
+ ///
+ /// Raised when the visibility of the encapsulated task pane changed.
+ ///
+ public event EventHandler VisibilityChanged;
+
+ #endregion
+
+ #region Constructor
+
+ private TaskPaneManager()
+ {
+ _width = UserSettings.UserSettings.Default.TaskPaneWidth;
+ _viewModel = new WorkbookViewModel(Instance.Default.ActiveWorkbook);
+ AttachToCurrentWindow();
+ Excel.ViewModels.Instance.Default.Application.WindowActivate += Application_WindowActivate;
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private static void OnInitialized(TaskPaneManager taskPaneManager)
+ {
+ EventHandler h = Initialized;
+ if (h != null)
+ {
+ h(null, new TaskPaneManagerEventArgs(taskPaneManager));
+ }
+ }
+
+ private void OnVisibilityChanged(SheetManagerTaskPane sheetManagerTaskPane)
+ {
+ if (!_lockVisibleChangedEventHandler)
+ {
+ _lockVisibleChangedEventHandler = true;
+ Logger.Info("OnVisibilityChanged");
+
+ // Synchronize the visibility of all task panes.
+ // We cannot use our own Visible property to accomplish this,
+ // because accessing the property of the task pane that raised
+ // the event causes an exception.
+ _visible = sheetManagerTaskPane.Visible;
+ foreach (SheetManagerTaskPane p in Panes.Values)
+ {
+ if (sheetManagerTaskPane != p)
+ {
+ p.Visible = _visible;
+ }
+ }
+
+ Logger.Info("OnVisibilityChanged: Reraising VisibiltyChanged event");
+ EventHandler h = VisibilityChanged;
+ if (h != null)
+ {
+ h(this, new SheetManagerEventArgs(sheetManagerTaskPane));
+ }
+
+ UserSettings.UserSettings.Default.SheetManagerVisible = Visible;
+ _lockVisibleChangedEventHandler = false;
+ }
+ }
+
+ private void Application_WindowActivate(
+ Microsoft.Office.Interop.Excel.Workbook Wb,
+ Microsoft.Office.Interop.Excel.Window Wn)
+ {
+ Logger.Info("Application_WindowActivate");
+ AttachToCurrentWindow();
+ }
+
+ private void AttachToCurrentWindow()
+ {
+ // If the current window does not yet have our task pane, add it to it
+ IntPtr currentHandle = Bovender.Win32Window.MainWindowHandleProvider();
+ if (!Panes.ContainsKey(currentHandle))
+ {
+ Logger.Info("Attaching new WorksheetManager panel to window 0x{0:X08}", currentHandle);
+ WorkbookViewModel viewModel;
+ if (Instance.Default.IsSingleDocumentInterface)
+ {
+ // Create a new workbook view model only if this is an SDI application
+ viewModel = new WorkbookViewModel(Instance.Default.ActiveWorkbook);
+ }
+ else
+ {
+ viewModel = _viewModel;
+ }
+ SheetManagerTaskPane tp = new SheetManagerTaskPane(viewModel, Width, Visible);
+ tp.VisibilityChanged += (object sender, SheetManagerEventArgs args) =>
+ {
+ OnVisibilityChanged(args.TaskPane);
+ };
+ Panes.Add(currentHandle, tp);
+ }
+ else
+ {
+ Logger.Info("Window 0x{0:X08} already has a WorksheetManager panel", currentHandle);
+ }
+ }
+
+ #endregion
+
+ #region Private properties
+
+ ///
+ /// Manages the SheetManager task panes for individual Excel windows.
+ ///
+ ///
+ ///
+ /// Excel 2013 is an SDI application, which means it has multiple windows
+ /// for multiple workbooks. Excel 2010 is an MDI application, which means
+ /// that multiple open workbooks were shown in just a single application
+ /// window. The new SDI mode has consequences for task panes, which are
+ /// bound to each window.
+ ///
+ ///
+ /// Inspired by an answer by @antonio-nakic-alfirevic on StackOverflow:
+ /// http://stackoverflow.com/a/24732000/270712
+ ///
+ ///
+ /// More at https://msdn.microsoft.com/en-us/library/office/dn251093.aspx
+ ///
+ ///
+ private Dictionary Panes
+ {
+ get
+ {
+ return _lazyPanes.Value;
+ }
+ }
+
+ #endregion
+
+ #region Private fields
+
+ private WorkbookViewModel _viewModel;
+ private bool _visible;
+ private int _width;
+ private bool _lockVisibleChangedEventHandler;
+
+ #endregion
+
+ #region Private static fields
+
+ private static readonly Lazy _lazy = new Lazy(
+ () =>
+ {
+ Logger.Info("Lazily creating SheetManagerPane instance");
+ TaskPaneManager p = new TaskPaneManager();
+ OnInitialized(p);
+ return p;
+ }
+ );
+
+ private static readonly Lazy> _lazyPanes =
+ new Lazy>(() =>
+ {
+ return new Dictionary();
+ });
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/XLToolbox/SheetManager/TaskPaneManagerEventArgs.cs b/XLToolbox/SheetManager/TaskPaneManagerEventArgs.cs
new file mode 100755
index 00000000..5d557137
--- /dev/null
+++ b/XLToolbox/SheetManager/TaskPaneManagerEventArgs.cs
@@ -0,0 +1,34 @@
+/* TaskPaneManagerEventArgs.cs
+ * part of Daniel's XL Toolbox NG
+ *
+ * Copyright 2014-2016 Daniel Kraus
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace XLToolbox.SheetManager
+{
+ public class TaskPaneManagerEventArgs : EventArgs
+ {
+ public TaskPaneManager TaskPaneManager { get; private set; }
+
+ public TaskPaneManagerEventArgs(TaskPaneManager taskPaneManager)
+ {
+ TaskPaneManager = taskPaneManager;
+ }
+ }
+}
diff --git a/XLToolbox/Strings.Designer.cs b/XLToolbox/Strings.Designer.cs
index 108c67bc..02067af7 100755
--- a/XLToolbox/Strings.Designer.cs
+++ b/XLToolbox/Strings.Designer.cs
@@ -963,6 +963,15 @@ public static string InvalidKeySequence {
}
}
+ ///
+ /// Looks up a localized string similar to Sprache.
+ ///
+ public static string Language {
+ get {
+ return ResourceManager.GetString("Language", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Layout.
///
@@ -1332,6 +1341,15 @@ public static string Resolution {
}
}
+ ///
+ /// Looks up a localized string similar to You need to restart Excel for the changes to take effect..
+ ///
+ public static string RestartForChangesToTakeEffect {
+ get {
+ return ResourceManager.GetString("RestartForChangesToTakeEffect", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to RGB.
///
diff --git a/XLToolbox/Strings.de.resx b/XLToolbox/Strings.de.resx
new file mode 100755
index 00000000..12a31342
--- /dev/null
+++ b/XLToolbox/Strings.de.resx
@@ -0,0 +1,769 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Fehler!
+
+
+ Abbrechen
+
+
+ Auf Update prüfen
+
+
+ Suche nach Update...
+
+
+ Bitte geben Sie den Speicherort für das Update an
+
+
+ Schließen
+
+
+ Das Update kann nicht installiert werden, weil die Prüfsumme für die heruntergeladene Datei falsch ist. Das kann an einem Übertragungsfehler liegen oder an einem Festplattenfehler oder jemand hat die Datei manipuliert. Das Update wird jedenfalls nicht installiert.
+
+
+ Lade XL-Toolbox-Update herunter
+
+
+ Jetzt herunterladen
+
+
+ Die Update-Informationen konnten nicht heruntergeladen werden.
+Folgende Fehlermeldung kam zurück:
+{0}
+
+Bitte überprüfen Sie auch Ihre Internetverbindung.
+
+
+ Neue Version:
+
+
+ Eine neue Version von Daniel's XL Toolbox steht zum Download bereit.
+
+
+ OK
+
+
+ Update verfügbar
+
+
+ Fehler beim XL-Toolbox-Addin!
+
+
+ Das hier ist:
+
+
+ Das Update wurde heruntergeladen. Wenn Sie mit der Arbeit fertig sind und Excel beenden, wird es installiert.
+
+
+ Spenden
+
+
+ Das hier ist:
+
+
+ Willkommen
+
+
+ Willkommen bei Daniel's XL Toolbox
+
+
+ Was ist neu?
+
+
+ Zeigen Sie Ihre Anerkennung durch eine freiwillige Zahlung ("Spende"). Der Button unten führt Sie zur Homepage.
+
+
+ Felder löschen
+
+
+ E-Mail (optional)
+
+
+ Name (optional)
+
+
+ Bitte senden Sie einen Fehlerbericht. Wenn Sie Ihren Namen und E-Mail angeben, ermöglichen Sie dem Entwickler die Kontaktaufnahme zwecks erleichterter Fehlerbehebung. Klicken Sie auf "Techn. Informationen", um den Inhalt des Fehlerberichts zu sehen.
+
+
+ Bericht senden
+
+
+ Techn. Informationen...
+
+
+ Mir eine Kopie senden
+
+
+ CLR-Version
+
+
+ Excel-Bitness
+
+
+ Excel-Version
+
+
+ Ausnahme
+
+
+ Innere Ausnahme
+
+
+ Innere Beschreibung
+
+
+ Beschreibung
+
+
+ Betriebssystem-Bitness
+
+
+ Betriebssystem-Version
+
+
+ Funktionsaufrufstapel
+
+
+ Technische Informationen
+
+
+ XL-Toolbox-Version
+
+
+ Der Fehlerbericht konnte nicht gesendet werden.
+Folgende Meldung kam zurück:
+{0}
+
+
+ Der Fehlerbericht wurde erfolgreich gesendet.
+
+
+ Senden...
+
+
+ Öffentl. Kommentar (opt.)
+
+
+ Datenschutzerklärung: Die technischen Informationen werden in der öffentlichen XL-Toolbox-Fehlerliste veröffentlicht. Name und E-Mail (optional) werden jedoch NUR an den Programmierer gesendet und NICHT veröffentlicht. Falls Sie einen Kommentar eingeben, wird dieser EBENFALLS veröffentlicht.
+
+
+ Das vor einer Weile heruntergeladene XL-Toolbox-Update wird jetzt installiert.
+
+
+ Sie haben die neueste XL-Toolbox-Version. Es ist kein Update verfügbar.
+
+
+ Über Daniel's XL Toolbox
+
+
+ Version {0}
+
+
+ Danksagungen
+
+
+ Lizenz
+
+
+ Website
+
+
+ XL-Toolbox-Lizenz
+
+
+ Datenanalyse und Datenvisualisierung für Excel
+
+
+ Die URL für das Update ist:
+
+
+ Sie können das Update manuell herunterladen und zu installieren versuchen. Möglicherweise müssen Sie nach Rechtsklick auf die Datei den Befehl "Als Administrator ausführen" wählen.
+
+
+ Nicht für das Update authorisiert.
+
+
+ Dies ist freie und kostenlose Software.
+
+
+ Sie haben leider keine Schreibberechtigung für den Installationsordner der XL Toolbox. Deshalb können Sie das Update nicht ausführen. Bitte wenden Sie sich an Ihren System-Administrator, um das Update auszuführen.
+
+
+ Nein, danke.
+
+
+ FreeImage-Version
+
+
+ Nicht verfügbar
+
+
+ Tabellenblatt-Manager
+
+
+ Nach unten
+
+
+ Runter
+
+
+ Nach oben
+
+
+ Hoch
+
+
+ Löschen
+
+
+ Wollen Sie wirklich löschen? Das kann nicht rückgängig gemacht werden!
+
+
+ Nein
+
+
+ Ja
+
+
+ Bitte neuen Namen eingeben (1-31 Zeichen, darf [] /\ *? nicht enthalten).
+
+
+ Umbenennen
+
+
+ Bericht nicht abgeschickt.
+
+
+ Der Bericht wurde erfolgreich abgeschickt.
+
+
+ Beim Herunterladen ist ein Fehler aufgetreten:
+
+"{0}".
+
+Evtl. müssen Sie es noch einmal versuchen.
+
+
+ Index
+ For use as placeholder in file name templates
+
+
+ Arbeitsmappe
+ For use as placeholder in file name templates
+
+
+ Tabellenblatt
+ For use as placeholder in file name templates
+
+
+ Bearbeiten
+
+
+ Exportieren
+
+
+ Höhe
+
+
+ Seitenverhältnis fixieren
+
+
+ Zurücksetzen
+
+
+ Einzelexport
+
+
+ Breite
+
+
+ Ausgabe
+
+
+ Vorgabe
+
+
+ Auswahl
+
+
+ Export-Vorgabe bearbeiten
+
+
+ Hinzufügen
+
+
+ Alle Dateien
+
+
+ Farbmodell
+
+
+ Details
+
+
+ EMF-Dateien (*.emf)
+
+
+ Dateityp
+
+
+ Dieses Programm
+
+
+ Layout
+
+
+ Objekte
+
+
+ PNG-Dateien (*.png)
+
+
+ Auflösung
+
+
+ Bereich
+
+
+ SVG-Dateien
+
+
+ TIFF-Dateien (*.tif)
+
+
+ Einheit
+
+
+ CMYK
+
+
+ Graustufen
+
+
+ Schwarz/Weiß
+
+
+ Name
+
+
+ RGB
+
+
+ Transparenz
+
+
+ Transparente Leinwand
+
+
+ Zeichnet die Graphik auf transparenter Leinwand. Wenn die exportierte Graphik eine weiße Hintergrundfläche enthält (z.B. ein Diagramm mit weißer Diagrammfläche), wird die Transparenz damit übermalt. In einem solchen Fall ist die Option "Transparentes Weiß" zu erwägen.
+
+
+ Transparentes Weiß
+
+
+ Zeichnet alle weißen Farben transparent.
+
+
+ Weiße Leinwand
+
+
+ Zeichnet die Graphik auf weißer Leinwand ohne Transparenz.
+
+
+ Wollen Sie diese Vorgabe wirklich entfernen?
+
+
+ Vorgabe entfernen
+
+
+ Aktuelles Tabellenblatt
+
+
+ Aktuelle Arbeitsmappe
+
+
+ Mehrfachexport
+
+
+ Alle graphischen Objekte
+
+
+ Nur Diagramme
+
+
+ Alle offenen Arbeitsmappen
+
+
+ Layout wie im Tabellenblatt
+
+
+ Einzelne Graphikobjekte
+
+
+ Dateinamen-Schema
+
+
+ Verwenden Sie {Arbeitsmappe}, {Tabellenblatt} und {Index} (jeweils mit geschweiften Klammern) als Platzhalter. Die Dateinamen-Erweiterung können Sie weglassen. Nach dem Zielordner werden Sie gefragt, wenn Sie auf "exportieren" klicken.
+ Should contain localized versions of Strings.Workbook and Strings.Worksheet
+
+
+ Sofern nicht gemäß geltendem Recht vorgeschrieben oder schriftlich vereinbart, erfolgt die Bereitstellung dieser im Rahmen der Apache-Lizenz verbreiteten Software OHNE GEWÄHR ODER VORBEHALTE – ganz gleich, ob ausdrücklich oder stillschweigend. Informationen über die jeweiligen Bedingungen für Genehmigungen und Einschränkungen im Rahmen der Lizenz finden Sie in der Lizenz.
+
+
+ Ohne Garantie ‒ siehe Lizenzbedingungen
+
+
+ Fehlerbericht-Einsendung
+
+
+ Fehlerbericht konnte nicht abgeschickt werden.
+
+
+ Sende Bericht
+
+
+ Farbmanagement
+
+
+ Farbprofil
+
+
+ Farbmanagement verwenden
+
+
+ Daniel's XL Toolbox Update
+
+
+ Immer zuoberst
+
+
+ Export in Screenshot-Qualität
+
+
+ Der Screenshot-Export funktioniert nur mit graphischen Objekten. Bitte markieren Sie eine Graphik (Zeichnung oder Diagramm).
+
+
+ Mich fragen
+
+
+ Alle verwerfen
+
+
+ Wie wollen Sie beenden?
+
+
+ Excel beenden
+
+
+ Alle speichern
+
+
+ nicht gespeicherte Arbeitsmappen
+
+
+ Geöffnete Arbeitsmappen
+
+
+ Sind Sie sicher?
+
+
+ Mich jeweils fragen
+
+
+ Excel beenden und Änderungen verwerfen
+
+
+ Excel beenden und alle Änderungen speichern
+
+
+ CSV-Einstellungen
+
+
+ Dezimaltrennzeichen
+
+
+ Datenfeld-Trennzeichen
+
+
+ Tausendertrennzeichen
+
+
+ CSV exportieren
+
+
+ CSV importieren
+
+
+ Diese Aktion benötigt eine Zellauswahl.
+
+
+ Es müssen Zellen ausgewählt sein
+
+
+ Bovender-Framework
+
+
+ CSV-Export fehlgeschlagen
+
+
+ Verwenden Sie \t für Tabulator.
+
+
+ Obsolete XL Toolbox version found
+
+
+ Eine veraltete XL-Toolbox-Version wurde gefunden. Sie wird jetzt deaktiviert. Sie können alte Toolbox-Befehle auch in der neuen Version verwenden. Die alte Version können Sie über die Systemsteuerung deinstallieren.
+
+
+ Es werden jetzt die Standardeinstellungen verwendet.
+
+
+ Die Fehlermeldung lautet:
+
+
+ Persönliche Einstellungen
+
+
+ Ihre persönlichen XL-Toolbox-Einstellungen konnten nicht geladen werden.
+
+
+ Verfügbare Befehle
+
+
+ Tastaturkürzel bearbeiten
+
+
+ % ALT
+
+
+ Befehl:
+
+
+ ^ STRG
+
+
+ ^+{PgUp} STRG UMSCH BILD-HOCH
+
+
+ Tastaturkürzel bearbeiten
+
+
+ Tastaturkürzel aktivieren
+
+
+ Beispiel
+
+
+ Legende
+
+
+ Hilfstasten:
+
+
+ + UMSCH
+
+
+ Mehr Informationen über Tastaturkürzel (Microsoft-Website)
+
+
+ {F1}, {PgUp}, ... Spezialtasten
+
+
+ Enable XL Toolbox keyboard shortcuts
+
+
+ (Ungültige Tastaturkombination.)
+
+
+ Wollen Sie die technische Protokollierung jetzt aktivieren?
+
+
+ Wollen Sie die Log-Datei jetzt ansehen?
+
+
+ Wenn Sie glauben, ein Fehler in Daniel's XL Toolbox könnte die Ursache sein, schalten Sie bitte die technische Protokollierung (Log-Datei) ein. Das kann bei der Fehlersuche helfen.
+
+
+ Excel wurde zuletzt nicht ordentlich beendet
+
+
+ Sie haben ja schon die technische Protokollierung (Log-Datei) aktiviert. Die Log-Datei enthält möglicherweise Informationen, die für die Fehlersuche nützlich sind. Bitte senden Sie die Log-Datei doch an support@xltoolbox.net.
+
+
+ Das XL-Toolbox-Addin ist beim letzten Mal nicht sauber beendet worden.
+
+
+ Aktuelle Log-Datei:
+
+
+ Protokollierung aktivieren
+
+
+ Einstellungen der alten XL Toolbox bearbeiten
+
+
+ Einstellungen der alten Toolbox-Funktionen
+
+
+ Technische Protokollierung
+
+
+ Ordner für Einstellungen und Logdateien
+
+
+ Einige Funktionen stammen noch aus der alten Toolbox-Version (vor Version 7); ihre Einstellungen können Sie hier bearbeiten.
+
+
+ Breite des Aufgabenbereichs
+
+
+ Es ist technisch nicht möglich, die momentane Breite des Aufgabenbereichs beim Herunterfahren automatisch zu speichern und beim nächsten Start wiederherzustellen. Allerdings ist der hier angegebene Wert immer die tatsächliche momentane Breite des Aufgabenbereichs, sofern der Aufgabenbereich sichtbar ist.
+
+
+ Bildgröße: {0:0.00} Megapixel/{1:0.00} MB unkomprimiert.
+
+
+ Das Betriebssystem gewährt keinen Zugriff auf die Zwischenablage; wird sie vielleicht von einem anderen Programm blockiert?
+
+Fehlermeldung:
+
+{0}
+
+
+ Export fehlgeschlagen
+
+
+ Beim Export ist ein Fehler aufgetreten.
+
+Fehlermeldung:
+
+
+ Beim CSV-Export ist leider ein Fehler aufgetreten.
+
+Fehlermeldung:
+
+
+ Sprache
+
+
+ Sie müssen Excel neu starten, damit die Änderungen voll wirksam werden.
+
+
\ No newline at end of file
diff --git a/XLToolbox/Strings.resx b/XLToolbox/Strings.resx
index d8a14df6..9545f58b 100755
--- a/XLToolbox/Strings.resx
+++ b/XLToolbox/Strings.resx
@@ -1,6 +1,6 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
An error has occurred!
-
+
Cancel
-
+
Check for updates
-
+
Checking for updates
-
+
Please choose where to save the update file
-
+
Close
-
+
The downloaded file cannot be installed because it is different from the official update file. This can be caused by errors in the network connection, a faulty disk drive on your computer, or by someone hampering with the update process. The update will not be installed.
-
+
Downloading XL Toolbox update
-
+
Download now
-
+
Unable to fetch the current version information from the internet.
The error was:
{0}
Is your internet connection working?
-
+
New version:
-
+
A new version of the XL Toolbox is available for download.
-
+
OK
-
+
Update available
-
+
XL Toolbox Error!
-
+
You have:
-
+
The update has been successfully downloaded and will be installed when you quit Excel.
-
+
Donate
-
+
This is version:
-
+
Welcome
-
+
Welcome to the XL Toolbox add-in!
-
+
What's new?
-
+
Your voluntary payment ('donation') is greatly appreciated. To donate, click the button below.
-
+
Clear form
-
+
E-Mail (optional)
-
+
Name (optional)
-
+
Please send a crash report by clicking the button below. If you give your name and e-mail, the developer may contact you when trying to solve the problem. Click "Technical information..." to view the contents of the bug report.
-
+
Send crash report
-
+
Technical information...
-
+
Send me a copy of the e-mail to the developer
-
+
CLR version
-
+
Excel bitness
-
+
Excel version
-
+
Exception
-
+
Inner exception
-
+
Inner message
-
+
Message
-
+
OS bitness
-
+
OS version
-
+
Stack trace
-
+
Technical information
-
+
XL Toolbox version
-
+
Failed to submit the error report.
The following error occurred:
{0}
-
+
The error report was successfully submitted.
-
+
Sending...
-
+
Public comment (optional)
-
+
Privacy statement: The technical details will be published in the bug tracker online. Your name and e-mail (both optional) will ONLY be sent to the developer and NOT be shared. If you enter a comment below, the COMMENT WILL BE PUBLISHED anonymously along with the technical data online.
-
+
The update that you downloaded earlier will be installed now.
-
+
You already have the latest version of the XL Toolbox. No update available at this time.
-
+
About Daniel's XL Toolbox
-
+
Version {0}
-
+
Credits
-
+
License
-
+
Website
-
+
XL Toolbox License
-
+
Data analysis and visualization for Excel, for free.
-
+
The download URL is:
-
+
If you are the owner of this computer, you can download the update manually, then right-click the update installer and choose "Run as administrator" to acquire appropriate permissions to install.
-
+
Not authorized to update
-
+
This is free software.
-
+
However, you do not have write permissions to the folder that the XL Toolbox add-in was installed. Therefore you will not be able to automatically update this add-in. Please ask your system administrator to perform the update for you.
-
+
No, thanks
-
+
FreeImage version
-
+
Not available
-
+
Worksheet Manager
-
+
Bottom
-
+
Down
-
+
Top
-
+
Up
-
+
Delete
-
+
Do you really want to delete? This operation cannot be undone.
-
+
No
-
+
Yes
-
+
Please enter the desired new sheet name (1-31 characters, must not contain any of : [] /\ *?
-
+
Rename
-
+
Unable to submit the report.
-
+
The report was successfully submitted.
-
+
An error occurred while downloading the file:
"{0}".
You may want to try again.
-
+
indexFor use as placeholder in file name templates
-
+
workbookFor use as placeholder in file name templates
-
+
worksheetFor use as placeholder in file name templates
-
+
Edit
-
+
Export
-
+
Height
-
+
Preserve aspect ratio
-
+
Reset
-
+
Single graphic export
-
+
Width
-
+
Output
-
+
Preset
-
+
Selection
-
+
Edit export preset
-
+
Add
-
+
All files
-
+
Color space
-
+
Details
-
+
EMF files (*.emf)
-
+
File type
-
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
+
Layout
-
+
Objects
-
+
PNG files (*.png)
-
+
Resolution
-
+
Scope
-
+
SVG files
-
+
TIFF files (*.tif)
-
+
Unit
-
+
CMYK
-
+
Grays
-
+
Black & white
-
+
Name
-
+
RGB
-
+
Transparency
-
+
Transparent canvas
-
+
Leaves the canvas transparent. If the graphics object (e.g. the chart) that is exported contains white background color, the transparency will not be evident. In this case, if you want transparency, choose "Transparent white".
-
+
Transparent white
-
+
Forces all whites in the image file to become transparent.
-
+
White canvas
-
+
Paints the graphic object on a white canvas without transparency.
-
+
Do you really want to remove this preset?
-
+
Remove preset
-
+
Active worksheet
-
+
Active workbook
-
+
Batch export
-
+
All graphic objects
-
+
Only charts
-
+
All open workbooks
-
+
Preserve layout on sheet
-
+
Individual items
-
+
File name template
-
+
Use {workbook}, {worksheet} and {index} as placeholders. File extension can be omitted. Target directory will be queried when you click "Export".Should contain localized versions of Strings.Workbook and Strings.Worksheet
-
- This add-in is distributed under the Apache License, Version 2.0, on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+
+ Unless required by applicable law or agreed to in writing, software distributed under the Apache 2.0 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-
+
No warranties ‒ see license.
-
+
Crash Report Submission
-
+
Failed to submit crash report.
-
+
Submitting report
-
+
Color management
-
+
Color profile
-
+
Use color management
-
+
Daniel's XL Toolbox Update
-
+
Always on top
-
+
Screenshot-Quality Export
-
+
The screenshot-quality export works with graphical objects only. Please select a graphic (chart or shape).
-
+
Ask me
-
+
Discard all
-
+
How do you want to quit?
-
+
Quit Excel
-
+
Save all
-
+
Unsaved workbooks
-
+
Open workbooks
-
+
Are you sure?
-
+
Ask me as needed
-
+
Quit Excel, discarding changes
-
+
Quit Excel, saving all changed workbooks
-
+
CSV Settings
-
+
Decimal separator
-
+
Field separator
-
+
Thousands separator
-
+
Export CSV file
-
+
Import CSV file
-
+
This action requires a selection of cells.
-
+
Range selection required
-
+
Bovender framework
-
+
CSV export failed
-
+
Hint: Use \t to separate fields by tabs.
-
+
Obsolete XL Toolbox version found
-
+
An obsolete version of the XL Toolbox was found. It will be deactivated now. You can use old XL Toolbox commands in the new, Next-Generation version. You may want to uninstall the old version from your system using "Add/Remove Software".
-
+
Default settings will be used.
-
+
This is the error message:
-
+
Personal settings
-
+
Your personal XL Toolbox settings could not be loaded.
-
+
Available commands
-
+
Edit keyboard shortcuts
-
+
% ALT
-
+
Command:
-
+
^ CTRL
-
+
^+{PgUp} CTRL SHIFT PAGE-UP
-
+
Edit keyboard shortcut
-
+
Enable XL Toolbox keyboard shortcuts
-
+
Example
-
+
Legend
-
+
Modifier keys:
-
+
+ SHIFT
-
+
More help on shortcuts (Microsoft website)
-
+
{F1}, {PgUp}, ... Special keys
-
+
Enable XL Toolbox keyboard shortcuts
-
+
(Invalid key sequence.)
-
+
Do you want to enable logging now?
-
+
Do want to examine the log files now?
-
+
If you suspect that this could have been caused by a malfunction of the add-in, you may want to turn on the technical logging. The log file contents may be helpful in troubleshooting the issue.
-
+
Incomplete shutdown detected
-
+
You have already enabled logging. The log files may contain technical information that helps to identify the problem. Please consider sending the current log file to support@xltoolbox.net.
-
+
It appears that the XL Toolbox add-in was not shut down properly.
-
+
Current log:
-
+
Enable Logging
-
+
Edit legacy Toolbox preferences
-
+