Skip to content

Commit

Permalink
Merge pull request #30 from sveinungf/dev/custom-utf8
Browse files Browse the repository at this point in the history
SpreadsheetBuffer string interpolation handler
  • Loading branch information
sveinungf authored Dec 27, 2023
2 parents fdf3bdd + 876e80e commit 5debbb0
Show file tree
Hide file tree
Showing 22 changed files with 763 additions and 830 deletions.
12 changes: 6 additions & 6 deletions SpreadCheetah.Test/Helpers/CellFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ internal static class CellFactory

public static object Create(CellType cellType, CellValueType valueType, bool isNull, StyleId? styleId, out object? value) => valueType switch
{
CellValueType.Bool => CreateForBool(cellType, isNull, styleId, out value),
CellValueType.BoolFalse => CreateForBool(cellType, isNull ? null : false, styleId, out value),
CellValueType.BoolTrue => CreateForBool(cellType, isNull ? null : true, styleId, out value),
CellValueType.DateTime => CreateForDateTime(cellType, isNull, styleId, out value),
CellValueType.Decimal => CreateForDecimal(cellType, isNull, styleId, out value),
CellValueType.Double => CreateForDouble(cellType, isNull, styleId, out value),
Expand All @@ -106,7 +107,8 @@ internal static class CellFactory

public static Cell Create(Formula formula, CellValueType valueType, bool isNull, StyleId? styleId, out object? value) => valueType switch
{
CellValueType.Bool => CreateForBool(formula, isNull, styleId, out value),
CellValueType.BoolFalse => CreateForBool(formula, isNull ? null : false, styleId, out value),
CellValueType.BoolTrue => CreateForBool(formula, isNull ? null : true, styleId, out value),
CellValueType.DateTime => CreateForDateTime(formula, isNull, styleId, out value),
CellValueType.Decimal => CreateForDecimal(formula, isNull, styleId, out value),
CellValueType.Double => CreateForDouble(formula, isNull, styleId, out value),
Expand All @@ -117,9 +119,8 @@ internal static class CellFactory
_ => throw new ArgumentOutOfRangeException(nameof(valueType), valueType, null)
};

private static object CreateForBool(CellType cellType, bool isNull, StyleId? styleId, out object? value)
private static object CreateForBool(CellType cellType, bool? actualValue, StyleId? styleId, out object? value)
{
bool? actualValue = isNull ? null : true;
value = actualValue;

return cellType switch
Expand All @@ -131,9 +132,8 @@ private static object CreateForBool(CellType cellType, bool isNull, StyleId? sty
};
}

private static Cell CreateForBool(Formula formula, bool isNull, StyleId? styleId, out object? value)
private static Cell CreateForBool(Formula formula, bool? actualValue, StyleId? styleId, out object? value)
{
bool? actualValue = !isNull ? true : null;
value = actualValue;
return new Cell(formula, actualValue, styleId);
}
Expand Down
3 changes: 2 additions & 1 deletion SpreadCheetah.Test/Helpers/CellValueType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public enum CellValueType
Double,
Decimal,
DateTime,
Bool
BoolTrue,
BoolFalse
}
2 changes: 1 addition & 1 deletion SpreadCheetah.Test/Helpers/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace SpreadCheetah.Test.Helpers;
internal static class TestData
{
private static readonly CellType[] CellTypeArray = EnumHelper.GetValues<CellType>();
private static readonly CellType[] StyledCellTypeArray = new[] { CellType.StyledCell, CellType.Cell };
private static readonly CellType[] StyledCellTypeArray = [CellType.StyledCell, CellType.Cell];
private static readonly CellValueType[] CellValueTypeArray = EnumHelper.GetValues<CellValueType>();
private static readonly RowCollectionType[] RowCollectionTypeArray = EnumHelper.GetValues<RowCollectionType>();

Expand Down
80 changes: 51 additions & 29 deletions SpreadCheetah.Test/Tests/SpreadsheetFormulaRowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,19 @@ public async Task Spreadsheet_AddRow_CellWithFormulaAndStyle(bool bold)
// Arrange
const string formulaText = "SUM(A1,A2)";
using var stream = new MemoryStream();
await using (var spreadsheet = await Spreadsheet.CreateNewAsync(stream))
{
await spreadsheet.StartWorksheetAsync("Sheet");
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream);
await spreadsheet.StartWorksheetAsync("Sheet");

var style = new Style();
style.Font.Bold = bold;
var styleId = spreadsheet.AddStyle(style);
var style = new Style();
style.Font.Bold = bold;
var styleId = spreadsheet.AddStyle(style);

var formula = new Formula(formulaText);
var cell = new Cell(formula, styleId);
var formula = new Formula(formulaText);
var cell = new Cell(formula, styleId);

// Act
await spreadsheet.AddRowAsync(cell);
await spreadsheet.FinishAsync();
}
// Act
await spreadsheet.AddRowAsync(cell);
await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
Expand Down Expand Up @@ -108,30 +106,54 @@ public async Task Spreadsheet_AddRow_CellWithFormulaAndCachedValue(CellValueType
Assert.Equal(valueType.GetExpectedDefaultNumberFormat() ?? "", actualCell.Style.NumberFormat.Format);
}

[Fact]
public async Task Spreadsheet_AddRow_CellWithFormulaAndCachedDateTimeValueWithoutDefaultStyle()
{
// Arrange
const string formulaText = "SUM(A1,A2)";
using var stream = new MemoryStream();
var options = new SpreadCheetahOptions { DefaultDateTimeFormat = null };
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream, options);
await spreadsheet.StartWorksheetAsync("Sheet");
var formula = new Formula(formulaText);
var cachedValue = new DateTime(2020, 1, 2, 3, 4, 5, DateTimeKind.Utc);
var cell = new Cell(formula, cachedValue);

// Act
await spreadsheet.AddRowAsync(cell);
await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.Single();
var actualCell = worksheet.Cell(1, 1);
Assert.Equal(formulaText, actualCell.FormulaA1);
Assert.Equal(cachedValue.ToOADate(), actualCell.GetValue<double>(), 0.0001);
}

public static IEnumerable<object?[]> ItalicWithValueTypes() => TestData.CombineWithValueTypes(true, false);

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task Spreadsheet_AddRow_CellWithFormulaAndStyleAndCachedValue(bool italic)
[MemberData(nameof(ItalicWithValueTypes))]
public async Task Spreadsheet_AddRow_CellWithFormulaAndStyleAndCachedValue(bool italic, CellValueType cachedValueType, RowCollectionType rowType, bool cachedValueIsNull)
{
// Arrange
const string formulaText = "SUM(A1,A2)";
const int cachedValue = int.MinValue;
using var stream = new MemoryStream();
await using (var spreadsheet = await Spreadsheet.CreateNewAsync(stream))
{
await spreadsheet.StartWorksheetAsync("Sheet");
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream);
await spreadsheet.StartWorksheetAsync("Sheet");

var style = new Style();
style.Font.Italic = italic;
var styleId = spreadsheet.AddStyle(style);
var style = new Style();
style.Font.Italic = italic;
var styleId = spreadsheet.AddStyle(style);

var formula = new Formula(formulaText);
var cell = new Cell(formula, cachedValue, styleId);
var formula = new Formula(formulaText);
var cell = CellFactory.Create(formula, cachedValueType, cachedValueIsNull, styleId, out var cachedValue);

// Act
await spreadsheet.AddRowAsync(cell);
await spreadsheet.FinishAsync();
}
// Act
await spreadsheet.AddRowAsync(cell, rowType);
await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
Expand All @@ -140,7 +162,7 @@ public async Task Spreadsheet_AddRow_CellWithFormulaAndStyleAndCachedValue(bool
var actualCell = worksheet.Cell(1, 1);
Assert.Equal(formulaText, actualCell.FormulaA1);
Assert.Equal(italic, actualCell.Style.Font.Italic);
Assert.Equal(cachedValue, actualCell.CachedValue.GetNumber());
Assert.Equal(cachedValue.GetExpectedCachedValueAsString(), actualCell.CachedValue.ToString(CultureInfo.InvariantCulture));
}

[Theory]
Expand Down
27 changes: 27 additions & 0 deletions SpreadCheetah.Test/Tests/SpreadsheetRowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,33 @@ public async Task Spreadsheet_AddRow_ExplicitCellReferencesForLongStringValueCel
Assert.Equal(expectedRow1Refs, actualSheet2Refs);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task Spreadsheet_AddRow_ExplicitCellReferenceForDateTimeCellWithDefaultStyling(bool isNull)
{
// Arrange
using var stream = new MemoryStream();
var options = new SpreadCheetahOptions { WriteCellReferenceAttributes = true };
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream, options);
await spreadsheet.StartWorksheetAsync("Sheet1");

DateTime? cellValue = isNull ? null : new DateTime(2019, 8, 7, 6, 5, 4, DateTimeKind.Utc);
var cell = new Cell(cellValue);

// Act
await spreadsheet.AddRowAsync(cell);
await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
using var actual = SpreadsheetDocument.Open(stream, true);
var sheetPart = Assert.Single(actual.WorkbookPart!.WorksheetParts);
var actualRow = Assert.Single(sheetPart.Worksheet.Descendants<Row>());
var actualCell = Assert.Single(actualRow.Descendants<OpenXmlCell>());
Assert.Equal("A1", actualCell.CellReference?.Value);
}

public static IEnumerable<object?[]> RowHeights() => TestData.CombineWithCellTypes<double?>(
0.1,
10d,
Expand Down
44 changes: 44 additions & 0 deletions SpreadCheetah.Test/Tests/SpreadsheetStyledRowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,50 @@ public async Task Spreadsheet_AddRow_ExplicitCellReferencesForStyledCells(CellVa
Assert.Equal(expectedRow1Refs, actualSheet2Refs);
}

[Theory]
[MemberData(nameof(TestData.StyledCellTypes), MemberType = typeof(TestData))]
public async Task Spreadsheet_AddRow_LongStringValueStyledCells(CellType cellType, RowCollectionType rowType)
{
// Arrange
using var stream = new MemoryStream();
var options = new SpreadCheetahOptions { BufferSize = SpreadCheetahOptions.MinimumBufferSize };
await using var spreadsheet = await Spreadsheet.CreateNewAsync(stream, options);
var value = new string('a', options.BufferSize * 2);
var style = new Style();
style.Fill.Color = Color.Thistle;
var styleId = spreadsheet.AddStyle(style);

var row1 = Enumerable.Range(1, 10).Select(_ => CellFactory.Create(cellType, value, styleId)).ToList();
var row2 = Enumerable.Range(1, 1).Select(_ => CellFactory.Create(cellType, value, styleId)).ToList();
var row3 = Enumerable.Range(1, 100).Select(_ => CellFactory.Create(cellType, value, styleId)).ToList();

// Act
await spreadsheet.StartWorksheetAsync("Sheet1");
await spreadsheet.AddRowAsync(row1, rowType);
await spreadsheet.AddRowAsync(row2, rowType);
await spreadsheet.AddRowAsync(row3, rowType);

await spreadsheet.StartWorksheetAsync("Sheet2");
await spreadsheet.AddRowAsync(row1, rowType);

await spreadsheet.FinishAsync();

// Assert
SpreadsheetAssert.Valid(stream);
using var actual = SpreadsheetDocument.Open(stream, true);
var sheetParts = actual.WorkbookPart!.WorksheetParts.ToList();
Assert.Equal(2, sheetParts.Count);

var sheet1Rows = sheetParts[0].Worksheet.Descendants<Row>().ToList();
Assert.Equal(3, sheet1Rows.Count);
Assert.All(sheet1Rows[0].Descendants<OpenXmlCell>(), x => Assert.Equal(value, x.InnerText));
Assert.All(sheet1Rows[1].Descendants<OpenXmlCell>(), x => Assert.Equal(value, x.InnerText));
Assert.All(sheet1Rows[2].Descendants<OpenXmlCell>(), x => Assert.Equal(value, x.InnerText));

var sheet2Row = Assert.Single(sheetParts[1].Worksheet.Descendants<Row>());
Assert.All(sheet2Row.Descendants<OpenXmlCell>(), x => Assert.Equal(value, x.InnerText));
}

[Theory]
[MemberData(nameof(TestData.StyledCellTypes), MemberType = typeof(TestData))]
public async Task Spreadsheet_AddRow_ExplicitCellReferencesForLongStringValueStyledCells(CellType cellType, RowCollectionType rowType)
Expand Down
Loading

0 comments on commit 5debbb0

Please sign in to comment.