Skip to content

Commit 58b1be2

Browse files
Merge branch 'dev' into master
2 parents 63c3ca4 + 4c3bc76 commit 58b1be2

File tree

1,118 files changed

+6578
-4957
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,118 files changed

+6578
-4957
lines changed

Changelog.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Change Log
22

3+
## v1.4.0
4+
5+
---
6+
Release Date: **30.08.2020**
7+
8+
- Added style reader to resolve dates and times properly
9+
- Added new data type TIME, represented by TimeSpan objects in reader and writer
10+
- Changed namespace from 'Styles' to 'NanoXLSX.Styles'
11+
- Added time (TimeSpan) examples to the demos
12+
- Updated documentation
13+
- Fixed some code formatting issues
14+
15+
### Notes:
16+
* To be consistent, the namespace of 'Styles' was changed to 'NanoXLSX.Styles'. Minor changes may be necessary in existing code if styles were used
17+
* Currently, the style reader resolves only number formats to determine dates and times, as well as custom formats. Other components like fonts, borders or fills are neglected at the moment
18+
19+
320
## v1.3.6
421

522
---

Demo/Program.cs

Lines changed: 114 additions & 92 deletions
Large diffs are not rendered by default.

Demo/Testing/Performance.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
66
*/
77

8+
using NanoXLSX.Styles;
89
using System;
910
using System.Collections.Generic;
1011
using System.Linq;
@@ -62,7 +63,7 @@ public static void StressTest(string filename, string sheetname, int rows, int c
6263
{
6364
for (j = 0; j < cols; j++)
6465
{
65-
s.AddNextCell(field[i][j], Styles.BasicStyles.Bold);
66+
s.AddNextCell(field[i][j], BasicStyles.Bold);
6667
}
6768
s.GoToNextRow();
6869
}

Demo/Testing/Utils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public static bool PseudoRandomBool()
104104
/// <param name="minLength">Minimum date</param>
105105
/// <param name="maxLength">Maximum date</param>
106106
/// <returns>Randomly generated DateTime</returns>
107-
/// <remarks>Excel, respectively its OADate function does not support a dates before 30th December 1899. Such dates will cause an exception in NanoXLSX</remarks>
107+
/// <remarks>Excel, respectively its OAdate function does not support a dates before January 1st 1900 and after December 31 9999. Such dates will cause an exception in NanoXLSX</remarks>
108108
public static DateTime PseduoRandomDate(DateTime min, DateTime max)
109109
{
110110
long ticks = PseudoRandomLong(min.Ticks, max.Ticks);

Executable/Documentation.chm

765 KB
Binary file not shown.

NanoXLSX/Cell.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
using System.Text;
1111
using System.Text.RegularExpressions;
1212
using NanoXLSX.Exceptions;
13-
using Styles;
13+
using NanoXLSX.Styles;
1414
using FormatException = NanoXLSX.Exceptions.FormatException;
1515

1616
namespace NanoXLSX
@@ -31,8 +31,10 @@ public enum CellType
3131
STRING,
3232
/// <summary>Type for all numeric types (long, integer and float and double)</summary>
3333
NUMBER,
34-
/// <summary>Type for dates and times (Note: Dates before 1900-01-01 are not allowed)</summary>
34+
/// <summary>Type for dates(Note: Dates before 1900-01-01 and after 9999-12-31 are not allowed)</summary>
3535
DATE,
36+
/// <summary>Type for times (Note: Internally handled as OAdate, represented by <see cref="TimeSpan"/>)</summary>
37+
TIME,
3638
/// <summary>Type for boolean</summary>
3739
BOOL,
3840
/// <summary>Type for Formulas (The cell will be handled differently)</summary>
@@ -164,7 +166,7 @@ public Cell(object value, CellType type)
164166
}
165167

166168
/// <summary>
167-
/// Constructor with value, cell type and address. The worksheet reference is set to null and must be assigned later
169+
/// Constructor with value, cell type and address as string. The worksheet reference is set to null and must be assigned later
168170
/// </summary>
169171
/// <param name="value">Value of the cell</param>
170172
/// <param name="type">Type of the cell</param>
@@ -181,6 +183,25 @@ public Cell(Object value, CellType type, string address)
181183
}
182184
}
183185

186+
/// <summary>
187+
/// Constructor with value, cell type and address as struct. The worksheet reference is set to null and must be assigned later
188+
/// </summary>
189+
/// <param name="value">Value of the cell</param>
190+
/// <param name="type">Type of the cell</param>
191+
/// <param name="address">Address struct of the cell</param>
192+
public Cell(Object value, CellType type, Address address)
193+
{
194+
DataType = type;
195+
Value = value;
196+
columnNumber = address.Column;
197+
rowNumber = address.Row;
198+
WorksheetReference = null;
199+
if (type == CellType.DEFAULT)
200+
{
201+
ResolveCellType();
202+
}
203+
}
204+
184205
/// <summary>
185206
/// Constructor with value, cell type, row number, column number and the link to a worksheet
186207
/// </summary>
@@ -261,6 +282,7 @@ public void ResolveCellType()
261282
else if (t == typeof(long) || t == typeof(ulong)) { DataType = CellType.NUMBER; }
262283
else if (t == typeof(short) || t == typeof(ushort)) { DataType = CellType.NUMBER; }
263284
else if (t == typeof(DateTime)) { DataType = CellType.DATE; } // Not native but standard
285+
else if (t == typeof(TimeSpan)) { DataType = CellType.TIME; } // Not native but standard
264286
else { DataType = CellType.STRING; } // Default (char, string, object)
265287
}
266288

@@ -344,6 +366,7 @@ public static List<Cell> ConvertArray<T>(List<T> list)
344366
else if (t == typeof(short)) { c = new Cell((short)o, CellType.NUMBER); }
345367
else if (t == typeof(ushort)) { c = new Cell((ushort)o, CellType.NUMBER); }
346368
else if (t == typeof(DateTime)){ c = new Cell((DateTime)o, CellType.DATE); }
369+
else if (t == typeof(TimeSpan)){ c = new Cell((TimeSpan)o, CellType.TIME); }
347370
else if (t == typeof(string)) { c = new Cell((string)o, CellType.STRING); }
348371
else // Default = unspecified object
349372
{

NanoXLSX/Exceptions/StyleException.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ public StyleException()
3333
public StyleException(string title, string message)
3434
: base(title + ": " + message)
3535
{ ExceptionTitle = title; }
36+
37+
/// <summary>
38+
/// Constructor with passed message and inner exception
39+
/// </summary>
40+
/// <param name="message">Message of the exception</param>
41+
/// <param name="inner">Inner exception</param>
42+
/// <param name="title">Title of the exception</param>
43+
public StyleException(string title, string message, Exception inner)
44+
: base(message, inner)
45+
{ ExceptionTitle = title; }
3646
}
3747

3848
}

NanoXLSX/ImportOptions.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* NanoXLSX is a small .NET library to generate and read XLSX (Microsoft Excel 2007 or newer) files in an easy and native way
3+
* Copyright Raphael Stoeckli © 2020
4+
* This library is licensed under the MIT License.
5+
* You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
6+
*/
7+
8+
using System;
9+
using System.Collections.Generic;
10+
11+
namespace NanoXLSX
12+
{
13+
/// <summary>
14+
/// The import options define global rules to import worksheets. The options are mainly to override particular cell types (e.g. interpretation of dates as numbers)
15+
/// </summary>
16+
public class ImportOptions
17+
{
18+
/// <summary>
19+
/// Column types to enforce during the import
20+
/// </summary>
21+
public enum ColumnType
22+
{
23+
/// <summary>
24+
/// Cells are tried to be imported as numbers (double)
25+
/// </summary>
26+
Numeric,
27+
/// <summary>
28+
/// Cells are tried to be imported as dates (DateTime)
29+
/// </summary>
30+
Date,
31+
/// <summary>
32+
/// Cells are tried to be imported as times (TimeSpan)
33+
/// </summary>
34+
Time,
35+
/// <summary>
36+
/// Cells are tried to be imported as bools
37+
/// </summary>
38+
Bool,
39+
/// <summary>
40+
/// Cells are all imported as strings, using the ToString() method
41+
/// </summary>
42+
String
43+
}
44+
45+
/// <summary>
46+
/// If true, date or time values (default style number 1 or 3) will be interpreted as numeric values globally. This option overrules possible column options, defined by <see cref="AddEnforcedColumn(int, ColumnType)"/>.
47+
/// </summary>
48+
public bool EnforceDateTimesAsNumbers { get; set; } = false;
49+
50+
51+
/// <summary>
52+
/// Type enforcing rules during import for particular columns
53+
/// </summary>
54+
public Dictionary<int, ColumnType> EnforcedColumnTypes { get; private set; } = new Dictionary<int, ColumnType>();
55+
56+
/// <summary>
57+
/// The row number (zero-based) where enforcing rules are started to be applied. This is, for instance, to prevent enforcing in a header row
58+
/// </summary>
59+
public int EnforcingStartRowNumber { get; set; } = 0;
60+
61+
/// <summary>
62+
/// Adds a type enforcing rule to the passed column address
63+
/// </summary>
64+
/// <param name="columnAddress">Column address (A to XFD)</param>
65+
/// <param name="type">Type to be enforced on the column</param>
66+
public void AddEnforcedColumn(string columnAddress, ColumnType type)
67+
{
68+
this.EnforcedColumnTypes.Add(Cell.ResolveColumn(columnAddress), type);
69+
}
70+
71+
/// <summary>
72+
/// Adds a type enforcing rule to the passed column number (zero-based)
73+
/// </summary>
74+
/// <param name="columnNumber">Column number (0-16383)</param>
75+
/// <param name="type">Type to be enforced on the column</param>
76+
public void AddEnforcedColumn(int columnNumber, ColumnType type)
77+
{
78+
this.EnforcedColumnTypes.Add(columnNumber, type);
79+
}
80+
}
81+
}

NanoXLSX/LowLevel/ReaderUtils.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Xml;
7+
8+
namespace NanoXLSX.LowLevel
9+
{
10+
/// <summary>
11+
/// Static class with common util methods, used during reading XLSX files
12+
/// </summary>
13+
public static class ReaderUtils
14+
{
15+
/// <summary>
16+
/// Gets the XML attribute of the passed XML node by its name
17+
/// </summary>
18+
/// <param name="targetName">Name of the target attribute</param>
19+
/// <param name="node">XML node that contains the attribute</param>
20+
/// <param name="fallbackValue">Optional fallback value if the attribute was not found. Default is null</param>
21+
/// <returns>Attribute value as string or default value if not found (can be null)</returns>
22+
public static string GetAttribute(string targetName, XmlNode node, string fallbackValue = null)
23+
{
24+
if (node.Attributes == null || node.Attributes.Count == 0)
25+
{
26+
return fallbackValue;
27+
}
28+
29+
foreach (XmlAttribute attribute in node.Attributes)
30+
{
31+
if (attribute.Name == targetName)
32+
{
33+
return attribute.Value;
34+
}
35+
}
36+
37+
return fallbackValue;
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)