Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace SharpExcel.Models.Attributes;
public class ExcelColumnDefinitionAttribute(string columnName, int width = -1, string? format = null)
: Attribute
{
public string DisplayName { get; set; } = columnName;
public string DisplayName { get; } = columnName;

public int ColumnWidth { get; set; } = width;
public int ColumnWidth { get; } = width;

public string? Format { get; set; } = format;
public string? Format { get; } = format;
}
2 changes: 1 addition & 1 deletion SharpExcel.Models/Configuration/ExporterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public ExporterOptions<TExportModel> WithStylingRule(Action<StylingRule<TExportM
/// <summary>
/// Fluent method to add a styling rule for this exporter
/// </summary>
/// <param name="stylingRuleOptions">constructs the styling rule</param>
/// <param name="targetingRuleOptions">constructs targeting rule</param>
/// <returns></returns>
public ExporterOptions<TExportModel> WithTarget(Action<TargetingRule<TExportModel>> targetingRuleOptions)
{
Expand Down
2 changes: 1 addition & 1 deletion SharpExcel.Models/Data/TargetingRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public record TargetingRule<TRecord> : ITargetingRule
/// REQUIRED: name of the sheet in the excel file
/// </summary>
[MinLength(1)]
public string SheetName { get; set; } = null!;
public string? SheetName { get; set; }

/// <summary>
/// Optional Row to start reading/writing from.
Expand Down
65 changes: 30 additions & 35 deletions SharpExcel/Exporters/BaseSharpExcelSynchronizer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using Microsoft.Extensions.Options;
using SharpExcel.Abstraction;
using SharpExcel.Extensions;
Expand Down Expand Up @@ -38,18 +37,26 @@ public Task<ExcelReadResult<TModel>> ReadWorkbookAsync(CultureInfo cultureInfo,
var output = new ExcelReadResult<TModel>();
var instanceData = CreateReadInstanceData(cultureInfo, workbook);

var rules = _options.Value.Targeting.Rules.GroupBy(rule => rule.SheetName);
var rules = _options.Value.Targeting.Rules.Where(rule => rule.SheetName is not null).GroupBy(rule => rule.SheetName);

foreach (var ruleGroup in rules)
{
if (!instanceData.Workbook.Worksheets.TryGetWorksheet(ruleGroup.Key, out var worksheet))
if (!instanceData.Workbook.Worksheets.TryGetWorksheet(ruleGroup.Key!, out var worksheet))
{
continue;
}

foreach (var rule in ruleGroup)
{
ReadSheetAsync(rule, output, instanceData, worksheet);
ReadSheet(rule, output, instanceData, worksheet);
}
}

if (workbook.Worksheets.Count > 0)
{
foreach (var rule in _options.Value.Targeting.Rules.Where(rule => rule.SheetName is null))
{
ReadSheet(rule, output, instanceData, workbook.Worksheets.First());
}
}

Expand All @@ -67,12 +74,19 @@ public virtual async Task<XLWorkbook> GenerateWorkbookAsync(CultureInfo cultureI

Dictionary<TargetingRule<TModel>, IEnumerable<TModel>> dataGroupedByTargetingRule = new();

if (!workbook.Worksheets.TryGetWorksheet(ExcelTargetingConstants<TModel>.DefaultTargetingRule.SheetName!, out _))
{
//create default sheet if it does not exist
workbook.Worksheets.Add(ExcelTargetingConstants<TModel>.DefaultTargetingRule.SheetName!);
}

foreach (var targetingRule in _options.Value.Targeting.Rules)
{
dataGroupedByTargetingRule.Add(targetingRule, data.Where(x => targetingRule.RulePredicate != null && targetingRule.RulePredicate(x)).ToList());
if (!workbook.Worksheets.TryGetWorksheet(targetingRule.SheetName, out var _))

if (targetingRule?.SheetName is not null && !workbook.Worksheets.TryGetWorksheet(targetingRule.SheetName, out _))
{
workbook.Worksheets.Add(targetingRule.SheetName);
workbook.Worksheets.Add((targetingRule?.SheetName ?? ExcelTargetingConstants<TModel>.DefaultTargetingRule.SheetName)!);
}
}

Expand All @@ -89,12 +103,11 @@ public virtual async Task<XLWorkbook> GenerateWorkbookAsync(CultureInfo cultureI
}


/// <inheritdoc />
internal virtual Task GenerateSheetAsync(TargetingRule<TModel> targetingRule, SharpExcelWriterInstanceData<TModel> instanceData, IEnumerable<TModel> data)
{
if (!instanceData.Workbook.Worksheets.TryGetWorksheet(targetingRule.SheetName, out var _))
if (!instanceData.Workbook.Worksheets.TryGetWorksheet((targetingRule.SheetName ?? ExcelTargetingConstants<TModel>.DefaultTargetingRule.SheetName)!, out _))
{
instanceData.Workbook.Worksheets.Add(targetingRule.SheetName);
instanceData.Workbook.Worksheets.Add(targetingRule.SheetName ?? ExcelTargetingConstants<TModel>.DefaultTargetingRule.SheetName!);
}

//start at Row 1 if not defined because Excel starts at 1
Expand All @@ -114,8 +127,7 @@ internal virtual Task GenerateSheetAsync(TargetingRule<TModel> targetingRule, Sh
return Task.CompletedTask;
}

/// <inheritdoc />
internal void ReadSheetAsync(TargetingRule<TModel> rule, ExcelReadResult<TModel> result, SharpExcelWriterInstanceData<TModel> instanceData, IXLWorksheet worksheet)
internal void ReadSheet(TargetingRule<TModel> rule, ExcelReadResult<TModel> result, SharpExcelWriterInstanceData<TModel> instanceData, IXLWorksheet worksheet)
{
var usedArea = worksheet.RangeUsed();
if (usedArea is null)
Expand All @@ -131,14 +143,6 @@ internal void ReadSheetAsync(TargetingRule<TModel> rule, ExcelReadResult<TModel>
{
var data = ReadRow(worksheet, instanceData, row.WorksheetRow(), out var validationResults);

if (data == null)
{
//skip to next record if we can't read record
continue;
}

result.Records.Add(data);

//add validation results
if (validationResults.Any())
{
Expand All @@ -150,8 +154,11 @@ internal void ReadSheetAsync(TargetingRule<TModel> rule, ExcelReadResult<TModel>
ValidationResults = validationResult.Value
});
}

continue;
}


result.Records.Add(data);
}
}

Expand All @@ -163,7 +170,7 @@ internal void ReadSheetAsync(TargetingRule<TModel> rule, ExcelReadResult<TModel>
/// <param name="row">row to read</param>
/// <param name="validationResults">A dictionary containing validation results of previous rows</param>
/// <returns></returns>
private static TModel? ReadRow(
private static TModel ReadRow(
IXLWorksheet sheet,
SharpExcelWriterInstanceData<TModel> instance,
IXLRow row,
Expand Down Expand Up @@ -212,9 +219,9 @@ internal void ReadSheetAsync(TargetingRule<TModel> rule, ExcelReadResult<TModel>
/// <summary>
/// Finds header row and maps the column order so we can fill them later
/// </summary>
/// <param name="rule"></param>
/// <param name="instance">instance data</param>
/// <param name="usedArea">total used area of the workbook</param>
/// <param name="sheet"></param>
/// <returns></returns>
private static int FindAndMapHeaderRow(
TargetingRule<TModel> rule,
Expand Down Expand Up @@ -243,7 +250,7 @@ private static int FindAndMapHeaderRow(

for (int i = startIndex; i <= usedArea.ColumnCount(); i++)
{
var cell = headerRow!.Cell(i);
var cell = headerRow.Cell(i);
if (!cell.TryGetValue(out string cellValue))
continue;

Expand All @@ -265,12 +272,6 @@ private static int FindAndMapHeaderRow(
return headerRowId <= 1 ? 2 : headerRowId - 1;
}

/// <summary>
/// Creates lookup data for the current export run
/// </summary>
/// <param name="arguments">arguments to use</param>
/// <param name="workbook">workbook to use</param>
/// <returns></returns>
private SharpExcelWriterInstanceData<TModel> CreateWriteInstanceData(CultureInfo cultureInfo, XLWorkbook workbook)
{
var random = new Random();
Expand All @@ -291,12 +292,6 @@ private SharpExcelWriterInstanceData<TModel> CreateWriteInstanceData(CultureInfo
return run;
}

/// <summary>
/// Creates lookup data for the current import run
/// </summary>
/// <param name="arguments">arguments to use</param>
/// <param name="workbook">workbook to use</param>
/// <returns></returns>
private SharpExcelWriterInstanceData<TModel> CreateReadInstanceData(CultureInfo cultureInfo, XLWorkbook workbook)
{
return new SharpExcelWriterInstanceData<TModel>()
Expand Down