1. add async method for all (QueryAsync & SaveAsAsync & SaveAsByTemplateAsync).

2. add async stuff unit tests.
3. replace tests\MiniExcelTests\Utils\PathHelper.cs for special path name.
4. add async benchmarks benchmarks\MiniExcel.Benchmarks\Program.cs
This commit is contained in:
damiel 2021-06-21 04:58:06 +08:00
parent f82a89d757
commit 5ad43c6ba7
18 changed files with 3096 additions and 22 deletions

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
@ -84,6 +85,20 @@ namespace MiniExcelLibs.Benchmarks
}
}
[Benchmark(Description = "MiniExcel Async Template Generate")]
public async Task MiniExcel_Template_Generate_Async_Test()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
const string templatePath = @"TestTemplateBasicIEmumerableFill.xlsx";
var value = new
{
employees = Enumerable.Range(1, runCount).Select(s => new { name = "Jack", department = "HR" })
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
}
}
[Benchmark(Description = "ClosedXml.Report Template Generate")]
public void ClosedXml_Report_Template_Generate_Test()
{
@ -236,6 +251,16 @@ namespace MiniExcelLibs.Benchmarks
File.Delete(path);
}
[Benchmark(Description = "MiniExcel Async Create Xlsx")]
public async Task MiniExcelCreateAsyncTest()
{
var values = GetValues();
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
using (var stream = File.Create(path))
await stream.SaveAsAsync(values);
File.Delete(path);
}
[Benchmark(Description = "ClosedXml Create Xlsx")]
public void ClosedXmlCreateTest()
{
@ -275,7 +300,7 @@ namespace MiniExcelLibs.Benchmarks
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook))
{
// Add a WorkbookPart to the document.

View File

@ -4,11 +4,12 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static MiniExcelLibs.Utils.Helpers;
namespace MiniExcelLibs.Csv
{
internal class CsvReader : IExcelReader
internal class CsvReader : IExcelReader , IExcelReaderAsync
{
private Stream _stream;
public CsvReader(Stream stream)
@ -127,5 +128,15 @@ namespace MiniExcelLibs.Csv
.Select(s => Regex.Replace(s.Replace("\"\"", "\""), "^\"|\"$", "")).ToArray();
//this code from S.O : https://stackoverflow.com/a/11365961/9131476
}
public Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, IConfiguration configuration)
{
return Task.Run(() => Query(UseHeaderRow, sheetName, startCell, configuration));
}
public Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, IConfiguration configuration) where T : class, new()
{
return Task.Run(() => Query<T>(sheetName, startCell, configuration));
}
}
}

View File

@ -6,11 +6,12 @@ using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static MiniExcelLibs.Utils.Helpers;
namespace MiniExcelLibs.Csv
{
internal class CsvWriter : IExcelWriter
internal class CsvWriter : IExcelWriter , IExcelWriterAsync
{
private Stream _stream;
@ -82,7 +83,7 @@ namespace MiniExcelLibs.Csv
//if(mode == null)
// throw new NotImplementedException($"Type {type?.Name} & genericType {genericType?.Name} not Implemented. please issue for me.");
if (keys.Count() == 0 && props == null)
if (keys.Count == 0 && props == null)
{
writer.Write(newLine);
return;
@ -211,6 +212,12 @@ namespace MiniExcelLibs.Csv
writer.Write(newLine);
}
}
public Task SaveAsAsync(object value, string sheetName, bool printHeader, IConfiguration configuration)
{
return Task.Run(() => SaveAs(value, sheetName, printHeader, configuration));
}
}
internal static class CsvValueTostringHelper

View File

@ -7,7 +7,7 @@
internal class ExcelWriterFactory
{
internal static IExcelWriter GetProvider(Stream stream,ExcelType excelType)
internal static IExcelWriterAsync GetProvider(Stream stream,ExcelType excelType)
{
switch (excelType)
{
@ -23,7 +23,7 @@
internal class ExcelReaderFactory
{
internal static IExcelReader GetProvider(Stream stream, ExcelType excelType)
internal static IExcelReaderAsync GetProvider(Stream stream, ExcelType excelType)
{
switch (excelType)
{
@ -39,7 +39,7 @@
internal class ExcelTemplateFactory
{
internal static IExcelTemplate GetProvider(Stream stream, ExcelType excelType= ExcelType.XLSX)
internal static IExcelTemplateAsync GetProvider(Stream stream, ExcelType excelType= ExcelType.XLSX)
{
switch (excelType)
{

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MiniExcelLibs
{
@ -7,4 +8,10 @@ namespace MiniExcelLibs
IEnumerable<IDictionary<string, object>> Query(bool UseHeaderRow, string sheetName,string startCell, IConfiguration configuration);
IEnumerable<T> Query<T>(string sheetName, string startCell, IConfiguration configuration) where T : class, new();
}
internal interface IExcelReaderAsync : IExcelReader
{
Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, IConfiguration configuration);
Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, IConfiguration configuration) where T : class, new();
}
}

View File

@ -1,8 +1,16 @@
namespace MiniExcelLibs
using System.Threading.Tasks;
namespace MiniExcelLibs
{
internal interface IExcelTemplate
{
void SaveAsByTemplate(string templatePath, object value);
void SaveAsByTemplate(byte[] templateBtyes, object value);
}
internal interface IExcelTemplateAsync : IExcelTemplate
{
Task SaveAsByTemplateAsync(string templatePath, object value);
Task SaveAsByTemplateAsync(byte[] templateBtyes, object value);
}
}

View File

@ -1,9 +1,15 @@
using System.IO;
using System.Threading.Tasks;
namespace MiniExcelLibs
{
internal interface IExcelWriter
internal interface IExcelWriter
{
void SaveAs(object value,string sheetName, bool printHeader, IConfiguration configuration);
}
internal interface IExcelWriterAsync : IExcelWriter
{
Task SaveAsAsync(object value, string sheetName, bool printHeader, IConfiguration configuration);
}
}

View File

@ -8,6 +8,7 @@
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
public static partial class MiniExcel
{
@ -19,13 +20,19 @@
SaveAs(stream, value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration);
}
public static Task SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null)
{
return Task.Run(() => SaveAs(path, value, printHeader, sheetName, excelType , configuration));
}
public static void SaveAs(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null)
{
if (string.IsNullOrEmpty(sheetName))
throw new InvalidDataException("Sheet name can not be empty or null");
if (excelType == ExcelType.UNKNOWN)
throw new InvalidDataException("Please specify excelType");
ExcelWriterFactory.GetProvider(stream, excelType).SaveAs(value, sheetName, printHeader, configuration);
GetWriterProvider(stream, sheetName, excelType).SaveAs(value, sheetName, printHeader, configuration);
}
public static Task SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null)
{
return GetWriterProvider(stream, sheetName, excelType).SaveAsAsync(value, sheetName, printHeader, configuration);
}
public static IEnumerable<T> Query<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new()
@ -40,6 +47,21 @@
return ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType)).Query<T>(sheetName, startCell, configuration);
}
public static Task<IEnumerable<dynamic>> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null)
{
return Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration));
}
public static Task<IEnumerable<T>> QueryAsync<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new()
{
return ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType)).QueryAsync<T>(sheetName, startCell, configuration);
}
public static Task<IEnumerable<T>> QueryAsync<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new()
{
return Task.Run(() => Query<T>(path, sheetName, excelType, startCell, configuration));
}
public static IEnumerable<dynamic> Query(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null)
{
using (var stream = Helpers.OpenSharedRead(path))
@ -52,6 +74,11 @@
return ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType)).Query(useHeaderRow, sheetName, startCell, configuration);
}
public static Task<IEnumerable<IDictionary<string, object>>> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null)
{
return GetReaderProvider(stream, excelType).QueryAsync(useHeaderRow, sheetName, startCell, configuration);
}
public static List<string> GetSheetNames(string path)
{
using (var stream = Helpers.OpenSharedRead(path))
@ -97,6 +124,27 @@
ExcelTemplateFactory.GetProvider(stream).SaveAsByTemplate(templateBytes, value);
}
public static Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value)
{
return ExcelTemplateFactory.GetProvider(stream).SaveAsByTemplateAsync(templatePath, value);
}
public static Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value)
{
return ExcelTemplateFactory.GetProvider(stream).SaveAsByTemplateAsync(templateBytes, value);
}
public static Task SaveAsByTemplateAsync(string path, string templatePath, object value)
{
return Task.Run(() => SaveAsByTemplate(path, templatePath, value));
}
public static Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value)
{
return Task.Run(() => SaveAsByTemplate(path, templateBytes, value));
}
/// <summary>
/// QueryAsDataTable is not recommended, because it'll load all data into memory.
/// </summary>
@ -106,6 +154,10 @@
return QueryAsDataTable(stream, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration);
}
public static Task<DataTable> QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null)
{
return Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration));
}
/// <summary>
/// QueryAsDataTable is not recommended, because it'll load all data into memory.
/// </summary>
@ -114,5 +166,19 @@
return ExcelOpenXmlSheetReader.QueryAsDataTableImpl(stream, useHeaderRow, ref sheetName, excelType, startCell, configuration);
}
private static IExcelWriterAsync GetWriterProvider(Stream stream, string sheetName, ExcelType excelType)
{
if (string.IsNullOrEmpty(sheetName))
throw new InvalidDataException("Sheet name can not be empty or null");
if (excelType == ExcelType.UNKNOWN)
throw new InvalidDataException("Please specify excelType");
return ExcelWriterFactory.GetProvider(stream, excelType);
}
private static IExcelReaderAsync GetReaderProvider(Stream stream, ExcelType excelType)
{
return ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType));
}
}
}

View File

@ -10,7 +10,7 @@ namespace MiniExcelLibs.OpenXml
{
internal static class DefualtOpenXml
{
private readonly static UTF8Encoding Utf8WithBom = new System.Text.UTF8Encoding(true);
private readonly static UTF8Encoding Utf8WithBom = new UTF8Encoding(true);
private static string DefaultRels = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Relationships xmlns=""http://schemas.openxmlformats.org/package/2006/relationships"">

View File

@ -8,12 +8,13 @@ using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using System.Xml;
using static MiniExcelLibs.Utils.Helpers;
namespace MiniExcelLibs.OpenXml
{
internal class ExcelOpenXmlSheetReader : IExcelReader
internal class ExcelOpenXmlSheetReader : IExcelReader, IExcelReaderAsync
{
private const string _ns = Config.SpreadsheetmlXmlns;
private List<SheetRecord> _sheetRecords;
@ -706,5 +707,15 @@ namespace MiniExcelLibs.OpenXml
return;
}
}
public Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, IConfiguration configuration)
{
return Task.Run(() => Query(UseHeaderRow, sheetName, startCell, configuration));
}
public Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, IConfiguration configuration) where T : class, new()
{
return Task.Run(() => Query<T>(sheetName, startCell, configuration));
}
}
}

View File

@ -8,6 +8,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static MiniExcelLibs.Utils.Helpers;
namespace MiniExcelLibs.OpenXml
@ -18,7 +19,7 @@ namespace MiniExcelLibs.OpenXml
public object Values { get; set; }
}
internal class ExcelOpenXmlSheetWriter : IExcelWriter
internal class ExcelOpenXmlSheetWriter : IExcelWriter , IExcelWriterAsync
{
private readonly static UTF8Encoding _utf8WithBom = new System.Text.UTF8Encoding(true);
private Stream _stream;
@ -480,5 +481,10 @@ namespace MiniExcelLibs.OpenXml
dimensionRef = $"A1:{Helpers.GetAlphabetColumnName(maxColumnIndex - 1)}{maxRowIndex}";
return dimensionRef;
}
public Task SaveAsAsync(object value, string sheetName, bool printHeader, IConfiguration configuration)
{
return Task.Run(() => SaveAs(value, sheetName, printHeader, configuration));
}
}
}

View File

@ -13,9 +13,10 @@ namespace MiniExcelLibs.OpenXml
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
internal partial class ExcelOpenXmlTemplate:IExcelTemplate
internal partial class ExcelOpenXmlTemplate:IExcelTemplate,IExcelTemplateAsync
{
private static readonly XmlNamespaceManager _ns;
private static readonly Regex _isExpressionRegex;
@ -66,7 +67,7 @@ namespace MiniExcelLibs.OpenXml
templateStream.CopyTo(stream);
var reader = new ExcelOpenXmlSheetReader(stream);
var _archive = new ExcelOpenXmlZip(stream, mode: ZipArchiveMode.Update, true, Encoding.UTF8);
using (var _archive = new ExcelOpenXmlZip(stream, mode: ZipArchiveMode.Update, true, Encoding.UTF8))
{
//read sharedString
var sharedStrings = reader.GetSharedStrings();
@ -93,9 +94,17 @@ namespace MiniExcelLibs.OpenXml
}
}
}
_archive.ZipFile.Dispose();
}
}
public Task SaveAsByTemplateAsync(string templatePath, object value)
{
return Task.Run(() => SaveAsByTemplate(templatePath, value));
}
public Task SaveAsByTemplateAsync(byte[] templateBtyes, object value)
{
return Task.Run(() => SaveAsByTemplate(templateBtyes, value));
}
}
}

View File

@ -0,0 +1,273 @@
using CsvHelper;
using MiniExcelLibs.Tests.Utils;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace MiniExcelLibs.Tests
{
public class MiniExcelCsvAsycTests
{
[Fact]
public async Task gb2312_Encoding_Read_Test()
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var path = PathHelper.GetSamplePath("csv/gb2312_Encoding_Read_Test.csv");
var config = new MiniExcelLibs.Csv.CsvConfiguration()
{
StreamReaderFunc = (stream) => new StreamReader(stream, encoding: Encoding.GetEncoding("gb2312"))
};
var q = await MiniExcel.QueryAsync(path, true, excelType: ExcelType.CSV, configuration: config);
var rows = q.ToList();
Assert.Equal("世界你好", rows[0].1);
}
[Fact]
public async Task SeperatorTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var values = new List<Dictionary<string, object>>()
{
new Dictionary<string,object>{{ "a", @"""<>+-*//}{\\n" }, { "b", 1234567890 },{ "c", true },{ "d", new DateTime(2021, 1, 1) } },
new Dictionary<string,object>{{ "a", @"<test>Hello World</test>" }, { "b", -1234567890 },{ "c", false },{ "d", new DateTime(2021, 1, 2) } },
};
await MiniExcel.SaveAsAsync(path, values, configuration: new MiniExcelLibs.Csv.CsvConfiguration() { Seperator = ';' });
var expected = @"a;b;c;d
""""""<>+-*//}{\\n"";1234567890;True;""2021-01-01 00:00:00""
""<test>Hello World</test>"";-1234567890;False;""2021-01-02 00:00:00""
";
Assert.Equal(expected, File.ReadAllText(path));
}
[Fact]
public async Task SaveAsByDictionary()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var table = new List<Dictionary<string, object>>();
await MiniExcel.SaveAsAsync(path, table);
Assert.Equal("\r\n", File.ReadAllText(path));
File.Delete(path);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var table = new Dictionary<string, object>(); //TODO
await MiniExcel.SaveAsAsync(path, table);
//Assert.Throws<NotImplementedException>(() => MiniExcel.SaveAs(path, table));
Assert.Equal("\r\n", File.ReadAllText(path));
File.Delete(path);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var values = new List<Dictionary<string, object>>()
{
new Dictionary<string,object>{{ "a", @"""<>+-*//}{\\n" }, { "b", 1234567890 },{ "c", true },{ "d", new DateTime(2021, 1, 1) } },
new Dictionary<string,object>{{ "a", @"<test>Hello World</test>" }, { "b", -1234567890 },{ "c", false },{ "d", new DateTime(2021, 1, 2) } },
};
await MiniExcel.SaveAsAsync(path, values);
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<dynamic>().ToList();
Assert.Equal(@"""<>+-*//}{\\n", records[0].a);
Assert.Equal(@"1234567890", records[0].b);
Assert.Equal(@"True", records[0].c);
Assert.Equal(@"2021-01-01 00:00:00", records[0].d);
Assert.Equal(@"<test>Hello World</test>", records[1].a);
Assert.Equal(@"-1234567890", records[1].b);
Assert.Equal(@"False", records[1].c);
Assert.Equal(@"2021-01-02 00:00:00", records[1].d);
}
File.Delete(path);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var values = new List<Dictionary<int, object>>()
{
new Dictionary<int,object>{{ 1, @"""<>+-*//}{\\n" }, { 2, 1234567890 },{ 3, true },{ 4, new DateTime(2021, 1, 1) } },
new Dictionary<int,object>{{ 1, @"<test>Hello World</test>" }, { 2, -1234567890 },{ 3, false },{4, new DateTime(2021, 1, 2) } },
};
await MiniExcel.SaveAsAsync(path, values);
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<dynamic>().ToList();
{
var row = records[0] as IDictionary<string, object>;
Assert.Equal(@"""<>+-*//}{\\n", row["1"]);
Assert.Equal(@"1234567890", row["2"]);
Assert.Equal(@"True", row["3"]);
Assert.Equal(@"2021-01-01 00:00:00", row["4"]);
}
{
var row = records[1] as IDictionary<string, object>;
Assert.Equal(@"<test>Hello World</test>", row["1"]);
Assert.Equal(@"-1234567890", row["2"]);
Assert.Equal(@"False", row["3"]);
Assert.Equal(@"2021-01-02 00:00:00", row["4"]);
}
}
File.Delete(path);
}
}
[Fact]
public async Task SaveAsByDataTableTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var table = new DataTable();
await MiniExcel.SaveAsAsync(path, table);
var text = File.ReadAllText(path);
Assert.Equal("\r\n", text);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.csv");
var table = new DataTable();
{
table.Columns.Add("a", typeof(string));
table.Columns.Add("b", typeof(decimal));
table.Columns.Add("c", typeof(bool));
table.Columns.Add("d", typeof(DateTime));
table.Rows.Add(@"""<>+-*//}{\\n", 1234567890, true, new DateTime(2021, 1, 1));
table.Rows.Add(@"<test>Hello World</test>", -1234567890, false, new DateTime(2021, 1, 2));
}
await MiniExcel.SaveAsAsync(path, table);
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<dynamic>().ToList();
Assert.Equal(@"""<>+-*//}{\\n", records[0].a);
Assert.Equal(@"1234567890", records[0].b);
Assert.Equal(@"True", records[0].c);
Assert.Equal(@"2021-01-01 00:00:00", records[0].d);
Assert.Equal(@"<test>Hello World</test>", records[1].a);
Assert.Equal(@"-1234567890", records[1].b);
Assert.Equal(@"False", records[1].c);
Assert.Equal(@"2021-01-02 00:00:00", records[1].d);
}
File.Delete(path);
}
}
public class Test
{
public string c1 { get; set; }
public string c2 { get; set; }
}
[Fact]
public async Task CsvExcelTypeTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
var input = new[] { new { A = "Test1", B = "Test2" } };
await MiniExcel.SaveAsAsync(path, input);
var texts = File.ReadAllLines(path);
Assert.Equal("A,B", texts[0]);
Assert.Equal("Test1,Test2", texts[1]);
{
var q = await MiniExcel.QueryAsync(path);
var rows = q.ToList();
Assert.Equal("A", rows[0].A);
Assert.Equal("B", rows[0].B);
Assert.Equal("Test1", rows[1].A);
Assert.Equal("Test2", rows[1].B);
}
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var rows = csv.GetRecords<dynamic>().ToList();
Assert.Equal("Test1", rows[0].A);
Assert.Equal("Test2", rows[0].B);
}
File.Delete(path);
}
}
[Fact()]
public async Task Create2x2_Test()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
await MiniExcel.SaveAsAsync(path, new[] {
new { c1 = "A1" ,c2 = "B1"},
new { c1 = "A2" ,c2 = "B2"},
});
using (var stream = File.OpenRead(path))
{
var rows = stream.Query(useHeaderRow: true, excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal("B1", rows[0].c2);
Assert.Equal("A2", rows[1].c1);
Assert.Equal("B2", rows[1].c2);
}
{
var rows = MiniExcel.Query(path, useHeaderRow: true, excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal("B1", rows[0].c2);
Assert.Equal("A2", rows[1].c1);
Assert.Equal("B2", rows[1].c2);
}
File.Delete(path);
}
[Fact()]
public async Task CsvTypeMappingTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.csv");
await MiniExcel.SaveAsAsync(path, new[] {
new { c1 = "A1" ,c2 = "B1"},
new { c1 = "A2" ,c2 = "B2"},
});
using (var stream = File.OpenRead(path))
{
var rows = stream.Query<Test>(excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal("B1", rows[0].c2);
Assert.Equal("A2", rows[1].c1);
Assert.Equal("B2", rows[1].c2);
}
{
var rows = MiniExcel.Query<Test>(path, excelType: ExcelType.CSV).ToList();
Assert.Equal("A1", rows[0].c1);
Assert.Equal("B1", rows[0].c2);
Assert.Equal("A2", rows[1].c1);
Assert.Equal("B2", rows[1].c2);
}
File.Delete(path);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
using Xunit;
using System.Linq;
using System;
using System.IO;
using System.Threading.Tasks;
namespace MiniExcelLibs.Tests
{
public partial class MiniExcelOpenXmlMultipleSheetAsyncTests
{
[Fact]
public async Task SpecifySheetNameQueryTest()
{
var path = @"../../../../../samples/xlsx/TestMultiSheet.xlsx";
{
var q = await MiniExcel.QueryAsync(path, sheetName: "Sheet3");
var rows = q.ToList();
Assert.Equal(5, rows.Count);
Assert.Equal(3, rows[0].A);
Assert.Equal(3, rows[0].B);
}
{
var q = await MiniExcel.QueryAsync(path, sheetName: "Sheet2");
var rows = q.ToList();
Assert.Equal(12, rows.Count);
Assert.Equal(1, rows[0].A);
Assert.Equal(1, rows[0].B);
}
{
var q = await MiniExcel.QueryAsync(path, sheetName: "Sheet1");
var rows = q.ToList();
Assert.Equal(12, rows.Count);
Assert.Equal(2, rows[0].A);
Assert.Equal(2, rows[0].B);
}
{
await Assert.ThrowsAsync<InvalidOperationException>(async() => {
var q= await MiniExcel.QueryAsync(path, sheetName: "xxxx");
q.ToList();
});
}
using (var stream = File.OpenRead(path))
{
{
var q = await stream.QueryAsync(sheetName: "Sheet3");
var rows = q.ToList();
Assert.Equal(5, rows.Count);
Assert.Equal(3d, rows[0]["A"]);
Assert.Equal(3d, rows[0]["B"]);
}
{
var q = await stream.QueryAsync(sheetName: "Sheet2");
var rows = q.ToList();
Assert.Equal(12, rows.Count);
Assert.Equal(1d, rows[0]["A"]);
Assert.Equal(1d, rows[0]["B"]);
}
{
var q = await stream.QueryAsync(sheetName: "Sheet1");
var rows = q.ToList();
Assert.Equal(12, rows.Count);
Assert.Equal(2d, rows[0]["A"]);
Assert.Equal(2d, rows[0]["B"]);
}
{
var q = await stream.QueryAsync(sheetName: "Sheet1");
var rows = q.ToList();
Assert.Equal(12, rows.Count);
Assert.Equal(2d, rows[0]["A"]);
Assert.Equal(2d, rows[0]["B"]);
}
}
}
[Fact]
public async Task MultiSheetsQueryBasicTest()
{
var path = @"../../../../../samples/xlsx/TestMultiSheet.xlsx";
using (var stream = File.OpenRead(path))
{
var sheet1 = await stream.QueryAsync(sheetName: "Sheet1");
var sheet2 = await stream.QueryAsync(sheetName: "Sheet2");
var sheet3 = await stream.QueryAsync(sheetName: "Sheet3");
}
}
[Fact]
public async Task MultiSheetsQueryTest()
{
var path = @"../../../../../samples/xlsx/TestMultiSheet.xlsx";
{
var sheetNames = MiniExcel.GetSheetNames(path).ToList();
foreach (var sheetName in sheetNames)
{
var rows = await MiniExcel.QueryAsync(path, sheetName: sheetName);
}
Assert.Equal(new[] { "Sheet2", "Sheet1", "Sheet3" }, sheetNames);
}
{
using (var stream = File.OpenRead(path))
{
var sheetNames = stream.GetSheetNames().ToList();
Assert.Equal(new[] { "Sheet2", "Sheet1", "Sheet3" }, sheetNames);
foreach (var sheetName in sheetNames)
{
var rows = await stream.QueryAsync(sheetName: sheetName);
}
}
}
}
}
}

View File

@ -0,0 +1,739 @@
using Dapper;
using MiniExcelLibs;
using MiniExcelLibs.Tests.Utils;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace MiniExcelTests
{
public class MiniExcelTemplateAsyncTests
{
[Fact]
public async Task DatatableTemptyRowTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
var managers = new DataTable();
{
managers.Columns.Add("name");
managers.Columns.Add("department");
}
var employees = new DataTable();
{
employees.Columns.Add("name");
employees.Columns.Add("department");
}
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = managers,
["employees"] = employees
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C5", demension);
}
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
var managers = new DataTable();
{
managers.Columns.Add("name");
managers.Columns.Add("department");
managers.Rows.Add("Jack", "HR");
}
var employees = new DataTable();
{
employees.Columns.Add("name");
employees.Columns.Add("department");
employees.Rows.Add("Wade", "HR");
}
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = managers,
["employees"] = employees
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C5", demension);
}
}
}
[Fact]
public async Task DatatableTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
var managers = new DataTable();
{
managers.Columns.Add("name");
managers.Columns.Add("department");
managers.Rows.Add("Jack", "HR");
managers.Rows.Add("Loan", "IT");
}
var employees = new DataTable();
{
employees.Columns.Add("name");
employees.Columns.Add("department");
employees.Rows.Add("Wade", "HR");
employees.Rows.Add("Felix", "HR");
employees.Rows.Add("Eric", "IT");
employees.Rows.Add("Keaton", "IT");
}
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = managers,
["employees"] = employees
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
}
{
var rows = MiniExcel.Query(path, sheetName: "Sheet2").ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
}
[Fact]
public async Task DapperTemplateTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
var connection = Db.GetConnection("Data Source=:memory:");
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = connection.Query("select 'Jack' name,'HR' department union all select 'Loan','IT'"),
["employees"] = connection.Query(@"select 'Wade' name,'HR' department union all select 'Felix','HR' union all select 'Eric','IT' union all select 'Keaton','IT'")
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
{
var rows = MiniExcel.Query(path, sheetName: "Sheet2").ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
}
[Fact]
public async Task DictionaryTemplateTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = new[] {
new Dictionary<string, object>{["name"]="Jack",["department"]="HR"},
new Dictionary<string, object>{["name"]="Loan",["department"]="IT"}
},
["employees"] = new[] {
new Dictionary<string, object>{["name"]="Wade",["department"]="HR"},
new Dictionary<string, object>{["name"]="Felix",["department"]="HR"},
new Dictionary<string, object>{["name"]="Eric",["department"]="IT"},
new Dictionary<string, object>{["name"]="Keaton",["department"]="IT"}
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
{
var rows = MiniExcel.Query(path, sheetName: "Sheet2").ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
}
[Fact]
public async Task TestGithubProject()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateGithubProjects.xlsx";
var projects = new[]
{
new {Name = "MiniExcel",Link="https://github.com/shps951023/MiniExcel",Star=146, CreateTime=new DateTime(2021,03,01)},
new {Name = "HtmlTableHelper",Link="https://github.com/shps951023/HtmlTableHelper",Star=16, CreateTime=new DateTime(2020,02,01)},
new {Name = "PocoClassGenerator",Link="https://github.com/shps951023/PocoClassGenerator",Star=16, CreateTime=new DateTime(2019,03,17)}
};
var value = new
{
User = "ITWeiHan",
Projects = projects,
TotalStar = projects.Sum(s => s.Star)
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("ITWeiHan Github Projects", rows[0].B);
Assert.Equal("Total Star : 178", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:D9", demension);
}
public class TestIEnumerableTypePoco
{
public string @string { get; set; }
public int? @int { get; set; }
public decimal? @decimal { get; set; }
public double? @double { get; set; }
public DateTime? datetime { get; set; }
public bool? @bool { get; set; }
public Guid? Guid { get; set; }
}
[Fact]
public async Task TestIEnumerableType()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestIEnumerableType.xlsx";
//1. By POCO
var poco = new TestIEnumerableTypePoco { @string = "string", @int = 123, @decimal = decimal.Parse("123.45"), @double = (double)123.33, @datetime = new DateTime(2021, 4, 1), @bool = true, @Guid = Guid.NewGuid() };
var value = new
{
Ts = new[] {
poco,
new TestIEnumerableTypePoco{},
null,
new TestIEnumerableTypePoco{},
poco
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query<TestIEnumerableTypePoco>(path).ToList();
Assert.Equal(poco.@string, rows[0].@string);
Assert.Equal(poco.@int, rows[0].@int);
Assert.Equal(poco.@double, rows[0].@double);
Assert.Equal(poco.@decimal, rows[0].@decimal);
Assert.Equal(poco.@bool, rows[0].@bool);
Assert.Equal(poco.datetime, rows[0].datetime);
Assert.Equal(poco.Guid, rows[0].Guid);
Assert.Null(rows[1].@string);
Assert.Null(rows[1].@int);
Assert.Null(rows[1].@double);
Assert.Null(rows[1].@decimal);
Assert.Null(rows[1].@bool);
Assert.Null(rows[1].datetime);
Assert.Null(rows[1].Guid);
// special input null but query is empty vo
Assert.Null(rows[2].@string);
Assert.Null(rows[2].@int);
Assert.Null(rows[2].@double);
Assert.Null(rows[2].@decimal);
Assert.Null(rows[2].@bool);
Assert.Null(rows[2].datetime);
Assert.Null(rows[2].Guid);
Assert.Null(rows[3].@string);
Assert.Null(rows[3].@int);
Assert.Null(rows[3].@double);
Assert.Null(rows[3].@decimal);
Assert.Null(rows[3].@bool);
Assert.Null(rows[3].datetime);
Assert.Null(rows[3].Guid);
Assert.Equal(poco.@string, rows[4].@string);
Assert.Equal(poco.@int, rows[4].@int);
Assert.Equal(poco.@double, rows[4].@double);
Assert.Equal(poco.@decimal, rows[4].@decimal);
Assert.Equal(poco.@bool, rows[4].@bool);
Assert.Equal(poco.datetime, rows[4].datetime);
Assert.Equal(poco.Guid, rows[4].Guid);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:G6", demension);
}
}
[Fact]
public async Task TestTemplateTypeMapping()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestITemplateTypeAutoMapping.xlsx";
//1. By POCO
var value = new TestIEnumerableTypePoco { @string = "string", @int = 123, @decimal = decimal.Parse("123.45"), @double = (double)123.33, @datetime = new DateTime(2021, 4, 1), @bool = true, @Guid = Guid.NewGuid() };
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query<TestIEnumerableTypePoco>(path).ToList();
Assert.Equal(value.@string, rows[0].@string);
Assert.Equal(value.@int, rows[0].@int);
Assert.Equal(value.@double, rows[0].@double);
Assert.Equal(value.@decimal, rows[0].@decimal);
Assert.Equal(value.@bool, rows[0].@bool);
Assert.Equal(value.datetime, rows[0].datetime);
Assert.Equal(value.Guid, rows[0].Guid);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:G2", demension);
}
}
[Fact]
public async Task TemplateCenterEmptyTest()
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateCenterEmpty.xlsx";
var value = new
{
Tests = Enumerable.Range(1, 5).Select((s, i) => new { test1 = i, test2 = i })
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
}
[Fact]
public async Task TemplateAsyncBasiTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
var templateBytes = File.ReadAllBytes(templatePath);
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
await MiniExcel.SaveAsByTemplateAsync(path, templateBytes, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
var templateBytes = File.ReadAllBytes(templatePath);
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
using (var stream = File.Create(path))
{
await stream.SaveAsByTemplateAsync(templateBytes, value);
}
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
// 2. By Dictionary
var value = new Dictionary<string, object>()
{
["Name"] = "Jack",
["CreateDate"] = new DateTime(2021, 01, 01),
["VIP"] = true,
["Points"] = 123
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
}
[Fact]
public async Task TestIEnumerable()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx";
//1. By POCO
var value = new
{
employees = new[] {
new {name="Jack",department="HR"},
new {name="Lisa",department="HR"},
new {name="John",department="HR"},
new {name="Mike",department="IT"},
new {name="Neo",department="IT"},
new {name="Loan",department="IT"}
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:B7", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx";
//2. By Dictionary
var value = new Dictionary<string, object>()
{
["employees"] = new[] {
new {name="Jack",department="HR"},
new {name="Lisa",department="HR"},
new {name="John",department="HR"},
new {name="Mike",department="IT"},
new {name="Neo",department="IT"},
new {name="Loan",department="IT"}
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:B7", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEmumerableFill.xlsx";
//3. By DataTable
var dt = new DataTable();
{
dt.Columns.Add("name");
dt.Columns.Add("department");
dt.Rows.Add("Jack", "HR");
dt.Rows.Add("Lisa", "HR");
dt.Rows.Add("John", "HR");
dt.Rows.Add("Mike", "IT");
dt.Rows.Add("Neo", "IT");
dt.Rows.Add("Loan", "IT");
}
var value = new Dictionary<string, object>()
{
["employees"] = dt
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:B7", demension);
}
}
[Fact]
public async Task TemplateTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
// 1. By Class
var value = new
{
title = "FooCompany",
managers = new[] {
new {name="Jack",department="HR"},
new {name="Loan",department="IT"}
},
employees = new[] {
new {name="Wade",department="HR"},
new {name="Felix",department="HR"},
new {name="Eric",department="IT"},
new {name="Keaton",department="IT"}
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
{
var rows = MiniExcel.Query(path).ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
{
var rows = MiniExcel.Query(path, sheetName: "Sheet2").ToList();
Assert.Equal(9, rows.Count);
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateComplex.xlsx";
// 2. By Dictionary
var value = new Dictionary<string, object>()
{
["title"] = "FooCompany",
["managers"] = new[] {
new {name="Jack",department="HR"},
new {name="Loan",department="IT"}
},
["employees"] = new[] {
new {name="Wade",department="HR"},
new {name="Felix",department="HR"},
new {name="Eric",department="IT"},
new {name="Keaton",department="IT"}
}
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("FooCompany", rows[0].A);
Assert.Equal("Jack", rows[2].B);
Assert.Equal("HR", rows[2].C);
Assert.Equal("Loan", rows[3].B);
Assert.Equal("IT", rows[3].C);
Assert.Equal("Wade", rows[5].B);
Assert.Equal("HR", rows[5].C);
Assert.Equal("Felix", rows[6].B);
Assert.Equal("HR", rows[6].C);
Assert.Equal("Eric", rows[7].B);
Assert.Equal("IT", rows[7].C);
Assert.Equal("Keaton", rows[8].B);
Assert.Equal("IT", rows[8].C);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C9", demension);
}
}
}
}

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace MiniExcelTests
@ -541,6 +542,111 @@ namespace MiniExcelTests
}
}
[Fact]
public async Task TemplateAsyncBasiTest()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
await MiniExcel.SaveAsByTemplateAsync(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
var templateBytes = File.ReadAllBytes(templatePath);
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
await MiniExcel.SaveAsByTemplateAsync(path, templateBytes, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
var templateBytes = File.ReadAllBytes(templatePath);
// 1. By POCO
var value = new
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};
using (var stream = File.Create(path))
{
await stream.SaveAsByTemplateAsync(templateBytes, value);
}
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateEasyFill.xlsx";
// 2. By Dictionary
var value = new Dictionary<string, object>()
{
["Name"] = "Jack",
["CreateDate"] = new DateTime(2021, 01, 01),
["VIP"] = true,
["Points"] = 123
};
MiniExcel.SaveAsByTemplate(path, templatePath, value);
var rows = MiniExcel.Query(path).ToList();
Assert.Equal("Jack", rows[1].A);
Assert.Equal("2021-01-01 00:00:00", rows[1].B);
Assert.Equal(true, rows[1].C);
Assert.Equal(123, rows[1].D);
Assert.Equal("Jack has 123 points", rows[1].E);
var demension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:E2", demension);
}
}
[Fact]
public void TestIEnumerable()
{

View File

@ -14,7 +14,7 @@
{
var method = (new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod();
var path = Path.Combine(Path.GetTempPath(), $"{method.DeclaringType.Name}_{method.Name}.{extension}");
var path = Path.Combine(Path.GetTempPath(), $"{method.DeclaringType.Name}_{method.Name}.{extension}").Replace("<", string.Empty).Replace(">", string.Empty);
if (File.Exists(path))
File.Delete(path);
return path;