mirror of
https://gitee.com/dotnetchina/MiniExcel.git
synced 2024-12-02 11:57:45 +08:00
code refactoring : SaveAs
This commit is contained in:
parent
c6eccfc981
commit
c8de5eccfe
@ -1,300 +1,10 @@
|
|||||||
namespace MiniExcelLibs
|
namespace MiniExcelLibs
|
||||||
{
|
{
|
||||||
using MiniExcelLibs.OpenXml;
|
|
||||||
using MiniExcelLibs.Zip;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Text;
|
|
||||||
using MiniExcelLibs.Utils;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
public static partial class MiniExcel
|
public static partial class MiniExcel
|
||||||
{
|
{
|
||||||
private readonly static UTF8Encoding Utf8WithBom = new System.Text.UTF8Encoding(true);
|
|
||||||
private static Dictionary<string, ZipPackageInfo> GetCreateXlsxInfos(object value, string startCell, bool printHeader)
|
|
||||||
{
|
|
||||||
var xy = ExcelOpenXmlUtils.ConvertCellToXY(startCell);
|
|
||||||
|
|
||||||
var defaultFiles = DefualtXml.GetDefaultFiles();
|
|
||||||
|
|
||||||
// dimension
|
|
||||||
var dimensionRef = "A1";
|
|
||||||
var maxRowIndex = 0;
|
|
||||||
var maxColumnIndex = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
var yIndex = xy.Item2;
|
|
||||||
|
|
||||||
if (value is DataTable)
|
|
||||||
{
|
|
||||||
var dt = value as DataTable;
|
|
||||||
|
|
||||||
// dimension
|
|
||||||
maxRowIndex = dt.Rows.Count;
|
|
||||||
maxColumnIndex = dt.Columns.Count;
|
|
||||||
|
|
||||||
|
|
||||||
if (printHeader)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
foreach (DataColumn c in dt.Columns)
|
|
||||||
{
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
|
||||||
sb.Append($"<x:v>{c.ColumnName}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < dt.Rows.Count; i++)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
|
|
||||||
for (int j = 0; j < dt.Columns.Count; j++)
|
|
||||||
{
|
|
||||||
var cellValue = dt.Rows[i][j];
|
|
||||||
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
|
||||||
var t = "t=\"str\"";
|
|
||||||
{
|
|
||||||
if (decimal.TryParse(cellValueStr, out var outV))
|
|
||||||
t = "t=\"n\"";
|
|
||||||
if (cellValue is bool)
|
|
||||||
{
|
|
||||||
t = "t=\"b\"";
|
|
||||||
cellValueStr = (bool)cellValue ? "1" : "0";
|
|
||||||
}
|
|
||||||
if (cellValue is DateTime || cellValue is DateTime?)
|
|
||||||
{
|
|
||||||
t = "s=\"1\"";
|
|
||||||
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
|
||||||
sb.Append($"<x:v>{cellValueStr}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IsDapperRowOrDictionaryStringObject(value))
|
|
||||||
{
|
|
||||||
var collection = value as IEnumerable<IDictionary<string, object>>;
|
|
||||||
|
|
||||||
var firstTime = true;
|
|
||||||
ICollection<string> keys = null;
|
|
||||||
foreach (var v in collection)
|
|
||||||
{
|
|
||||||
// head
|
|
||||||
if (firstTime)
|
|
||||||
{
|
|
||||||
firstTime = false;
|
|
||||||
if (v == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
keys = v.Keys;
|
|
||||||
maxColumnIndex = keys.Count;
|
|
||||||
if (printHeader)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
foreach (var key in keys)
|
|
||||||
{
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
|
||||||
sb.Append($"<x:v>{key}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//body
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
foreach (var p in keys)
|
|
||||||
{
|
|
||||||
var cellValue = v[p];
|
|
||||||
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
|
||||||
var t = "t=\"str\"";
|
|
||||||
{
|
|
||||||
if (decimal.TryParse(cellValueStr, out var outV))
|
|
||||||
t = "t=\"n\"";
|
|
||||||
if (cellValue is bool)
|
|
||||||
{
|
|
||||||
t = "t=\"b\"";
|
|
||||||
cellValueStr = (bool)cellValue ? "1" : "0";
|
|
||||||
}
|
|
||||||
if (cellValue is DateTime || cellValue is DateTime?)
|
|
||||||
{
|
|
||||||
t = "s=\"1\"";
|
|
||||||
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
|
||||||
sb.Append($"<x:v>{cellValueStr}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maxRowIndex = yIndex - 1;
|
|
||||||
}
|
|
||||||
else if (value is ICollection)
|
|
||||||
{
|
|
||||||
var collection = value as ICollection;
|
|
||||||
|
|
||||||
var props = Helpers.GetSubtypeProperties(collection);
|
|
||||||
|
|
||||||
maxColumnIndex = props.Length;
|
|
||||||
|
|
||||||
if (printHeader)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
foreach (var p in props)
|
|
||||||
{
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
|
||||||
sb.Append($"<x:v>{p.Name}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var v in collection)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
|
||||||
var xIndex = xy.Item1;
|
|
||||||
foreach (var p in props)
|
|
||||||
{
|
|
||||||
var cellValue = p.GetValue(v);
|
|
||||||
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
|
||||||
var t = "t=\"str\"";
|
|
||||||
{
|
|
||||||
if (decimal.TryParse(cellValueStr, out var outV))
|
|
||||||
t = "t=\"n\"";
|
|
||||||
if (cellValue is bool)
|
|
||||||
{
|
|
||||||
t = "t=\"b\"";
|
|
||||||
cellValueStr = (bool)cellValue ? "1" : "0";
|
|
||||||
}
|
|
||||||
if (cellValue is DateTime || cellValue is DateTime?)
|
|
||||||
{
|
|
||||||
t = "s=\"1\"";
|
|
||||||
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
|
||||||
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
|
||||||
sb.Append($"<x:v>{cellValueStr}");
|
|
||||||
sb.Append($"</x:v>");
|
|
||||||
sb.Append($"</x:c>");
|
|
||||||
xIndex++;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"</x:row>");
|
|
||||||
yIndex++;
|
|
||||||
}
|
|
||||||
maxRowIndex = yIndex - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException($"{value?.GetType().Name} type not implemented,please issue for me : https://github.com/shps951023/MiniExcel/issues");
|
|
||||||
}
|
|
||||||
|
|
||||||
// dimension
|
|
||||||
{
|
|
||||||
if (maxRowIndex == 0 && maxColumnIndex == 0)
|
|
||||||
dimensionRef = "A1";
|
|
||||||
else if (maxColumnIndex == 1)
|
|
||||||
dimensionRef = $"A{maxRowIndex}";
|
|
||||||
else
|
|
||||||
dimensionRef = $"A1:{Helpers.GetAlphabetColumnName(maxColumnIndex - 1)}{maxRowIndex}";
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultFiles[@"xl/worksheets/sheet1.xml"].Xml = $@"<?xml version=""1.0"" encoding=""utf-8""?>
|
|
||||||
<x:worksheet xmlns:x=""http://schemas.openxmlformats.org/spreadsheetml/2006/main"">
|
|
||||||
<dimension ref=""{dimensionRef}""/>
|
|
||||||
<x:sheetData>{sb.ToString()}</x:sheetData>
|
|
||||||
</x:worksheet>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsDapperRowOrDictionaryStringObject(object value)
|
|
||||||
{
|
|
||||||
return value is IEnumerable<IDictionary<string, object>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SaveAsImpl(string path, Dictionary<string, ZipPackageInfo> zipPackageInfos)
|
|
||||||
{
|
|
||||||
using (FileStream stream = new FileStream(path, FileMode.CreateNew))
|
|
||||||
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, false, Utf8WithBom))
|
|
||||||
CreteXlsxImpl(zipPackageInfos, archive);
|
|
||||||
}
|
|
||||||
private static void SaveAsImpl(Stream stream, Dictionary<string, ZipPackageInfo> zipPackageInfos)
|
|
||||||
{
|
|
||||||
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true, Utf8WithBom))
|
|
||||||
{
|
|
||||||
CreteXlsxImpl(zipPackageInfos, archive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreteXlsxImpl(Dictionary<string, ZipPackageInfo> zipPackageInfos, ZipArchive archive)
|
|
||||||
{
|
|
||||||
//[Content_Types].xml
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
|
|
||||||
<Types xmlns=""http://schemas.openxmlformats.org/package/2006/content-types"">
|
|
||||||
<Default ContentType=""application/xml"" Extension=""xml""/>
|
|
||||||
<Default ContentType=""application/vnd.openxmlformats-package.relationships+xml"" Extension=""rels""/>");
|
|
||||||
foreach (var p in zipPackageInfos)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"<Override ContentType=\"{p.Value.ContentType}\" PartName=\"/{p.Key}\" />");
|
|
||||||
}
|
|
||||||
sb.AppendLine("</Types>");
|
|
||||||
|
|
||||||
ZipArchiveEntry entry = archive.CreateEntry("[Content_Types].xml");
|
|
||||||
using (var zipStream = entry.Open())
|
|
||||||
using (StreamWriter writer = new StreamWriter(zipStream, Utf8WithBom))
|
|
||||||
writer.Write(sb.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var p in zipPackageInfos)
|
|
||||||
{
|
|
||||||
ZipArchiveEntry entry = archive.CreateEntry(p.Key);
|
|
||||||
using (var zipStream = entry.Open())
|
|
||||||
using (StreamWriter writer = new StreamWriter(zipStream, Utf8WithBom))
|
|
||||||
writer.Write(p.Value.Xml.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ExcelType GetExcelType(string filePath)
|
internal static ExcelType GetExcelType(string filePath)
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(filePath).ToLowerInvariant();
|
var extension = Path.GetExtension(filePath).ToLowerInvariant();
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
CsvWriter.SaveAs(stream, value);
|
CsvWriter.SaveAs(stream, value);
|
||||||
break;
|
break;
|
||||||
case ExcelType.XLSX:
|
case ExcelType.XLSX:
|
||||||
SaveAsImpl(stream, GetCreateXlsxInfos(value, startCell, printHeader));
|
ExcelOpenXmlSheetWriter.SaveAs(stream, value, startCell, printHeader);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Extension : {excelType} not suppprt");
|
throw new NotSupportedException($"Extension : {excelType} not suppprt");
|
||||||
@ -34,7 +34,7 @@
|
|||||||
CsvWriter.SaveAs(filePath, value);
|
CsvWriter.SaveAs(filePath, value);
|
||||||
break;
|
break;
|
||||||
case ExcelType.XLSX:
|
case ExcelType.XLSX:
|
||||||
SaveAsImpl(filePath, GetCreateXlsxInfos(value, startCell, printHeader));
|
ExcelOpenXmlSheetWriter.SaveAs(filePath, value, startCell, printHeader);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Extension : {Path.GetExtension(filePath)} not suppprt");
|
throw new NotSupportedException($"Extension : {Path.GetExtension(filePath)} not suppprt");
|
||||||
|
299
src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
Normal file
299
src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
using MiniExcelLibs.Utils;
|
||||||
|
using MiniExcelLibs.Zip;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MiniExcelLibs.OpenXml
|
||||||
|
{
|
||||||
|
internal class ExcelOpenXmlSheetWriter
|
||||||
|
{
|
||||||
|
internal static void SaveAs(string path, object value, string startCell, bool printHeader)
|
||||||
|
{
|
||||||
|
var zipPackageInfos = ExcelOpenXmlSheetWriter.GenerateXlsxPackages(value, startCell, printHeader);
|
||||||
|
|
||||||
|
using (FileStream stream = new FileStream(path, FileMode.CreateNew))
|
||||||
|
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, false, Utf8WithBom))
|
||||||
|
CreteXlsxImpl(zipPackageInfos, archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SaveAs(Stream stream, object value, string startCell, bool printHeader)
|
||||||
|
{
|
||||||
|
var zipPackageInfos = ExcelOpenXmlSheetWriter.GenerateXlsxPackages(value, startCell, printHeader);
|
||||||
|
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true, Utf8WithBom))
|
||||||
|
CreteXlsxImpl(zipPackageInfos, archive);
|
||||||
|
}
|
||||||
|
internal static Dictionary<string, ZipPackageInfo> GenerateXlsxPackages(object value, string startCell, bool printHeader)
|
||||||
|
{
|
||||||
|
var xy = ExcelOpenXmlUtils.ConvertCellToXY(startCell);
|
||||||
|
|
||||||
|
var defaultFiles = DefualtXml.GetDefaultFiles();
|
||||||
|
|
||||||
|
// dimension
|
||||||
|
var dimensionRef = "A1";
|
||||||
|
var maxRowIndex = 0;
|
||||||
|
var maxColumnIndex = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var yIndex = xy.Item2;
|
||||||
|
|
||||||
|
if (value is DataTable)
|
||||||
|
{
|
||||||
|
var dt = value as DataTable;
|
||||||
|
|
||||||
|
// dimension
|
||||||
|
maxRowIndex = dt.Rows.Count;
|
||||||
|
maxColumnIndex = dt.Columns.Count;
|
||||||
|
|
||||||
|
|
||||||
|
if (printHeader)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
foreach (DataColumn c in dt.Columns)
|
||||||
|
{
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
||||||
|
sb.Append($"<x:v>{c.ColumnName}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dt.Rows.Count; i++)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
|
||||||
|
for (int j = 0; j < dt.Columns.Count; j++)
|
||||||
|
{
|
||||||
|
var cellValue = dt.Rows[i][j];
|
||||||
|
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
||||||
|
var t = "t=\"str\"";
|
||||||
|
{
|
||||||
|
if (decimal.TryParse(cellValueStr, out var outV))
|
||||||
|
t = "t=\"n\"";
|
||||||
|
if (cellValue is bool)
|
||||||
|
{
|
||||||
|
t = "t=\"b\"";
|
||||||
|
cellValueStr = (bool)cellValue ? "1" : "0";
|
||||||
|
}
|
||||||
|
if (cellValue is DateTime || cellValue is DateTime?)
|
||||||
|
{
|
||||||
|
t = "s=\"1\"";
|
||||||
|
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
||||||
|
sb.Append($"<x:v>{cellValueStr}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsDapperRowOrDictionaryStringObject(value))
|
||||||
|
{
|
||||||
|
var collection = value as IEnumerable<IDictionary<string, object>>;
|
||||||
|
|
||||||
|
var firstTime = true;
|
||||||
|
ICollection<string> keys = null;
|
||||||
|
foreach (var v in collection)
|
||||||
|
{
|
||||||
|
// head
|
||||||
|
if (firstTime)
|
||||||
|
{
|
||||||
|
firstTime = false;
|
||||||
|
if (v == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
keys = v.Keys;
|
||||||
|
maxColumnIndex = keys.Count;
|
||||||
|
if (printHeader)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
foreach (var key in keys)
|
||||||
|
{
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
||||||
|
sb.Append($"<x:v>{key}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//body
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
foreach (var p in keys)
|
||||||
|
{
|
||||||
|
var cellValue = v[p];
|
||||||
|
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
||||||
|
var t = "t=\"str\"";
|
||||||
|
{
|
||||||
|
if (decimal.TryParse(cellValueStr, out var outV))
|
||||||
|
t = "t=\"n\"";
|
||||||
|
if (cellValue is bool)
|
||||||
|
{
|
||||||
|
t = "t=\"b\"";
|
||||||
|
cellValueStr = (bool)cellValue ? "1" : "0";
|
||||||
|
}
|
||||||
|
if (cellValue is DateTime || cellValue is DateTime?)
|
||||||
|
{
|
||||||
|
t = "s=\"1\"";
|
||||||
|
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
||||||
|
sb.Append($"<x:v>{cellValueStr}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maxRowIndex = yIndex - 1;
|
||||||
|
}
|
||||||
|
else if (value is ICollection)
|
||||||
|
{
|
||||||
|
var collection = value as ICollection;
|
||||||
|
|
||||||
|
var props = Helpers.GetSubtypeProperties(collection);
|
||||||
|
|
||||||
|
maxColumnIndex = props.Length;
|
||||||
|
|
||||||
|
if (printHeader)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
foreach (var p in props)
|
||||||
|
{
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" t=\"str\">");
|
||||||
|
sb.Append($"<x:v>{p.Name}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var v in collection)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<x:row r=\"{yIndex.ToString()}\">");
|
||||||
|
var xIndex = xy.Item1;
|
||||||
|
foreach (var p in props)
|
||||||
|
{
|
||||||
|
var cellValue = p.GetValue(v);
|
||||||
|
var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue);
|
||||||
|
var t = "t=\"str\"";
|
||||||
|
{
|
||||||
|
if (decimal.TryParse(cellValueStr, out var outV))
|
||||||
|
t = "t=\"n\"";
|
||||||
|
if (cellValue is bool)
|
||||||
|
{
|
||||||
|
t = "t=\"b\"";
|
||||||
|
cellValueStr = (bool)cellValue ? "1" : "0";
|
||||||
|
}
|
||||||
|
if (cellValue is DateTime || cellValue is DateTime?)
|
||||||
|
{
|
||||||
|
t = "s=\"1\"";
|
||||||
|
cellValueStr = ((DateTime)cellValue).ToOADate().ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var columname = ExcelOpenXmlUtils.ConvertXyToCell(xIndex, yIndex);
|
||||||
|
sb.Append($"<x:c r=\"{columname}\" {t}>");
|
||||||
|
sb.Append($"<x:v>{cellValueStr}");
|
||||||
|
sb.Append($"</x:v>");
|
||||||
|
sb.Append($"</x:c>");
|
||||||
|
xIndex++;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"</x:row>");
|
||||||
|
yIndex++;
|
||||||
|
}
|
||||||
|
maxRowIndex = yIndex - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"{value?.GetType().Name} type not implemented,please issue for me : https://github.com/shps951023/MiniExcel/issues");
|
||||||
|
}
|
||||||
|
|
||||||
|
// dimension
|
||||||
|
{
|
||||||
|
if (maxRowIndex == 0 && maxColumnIndex == 0)
|
||||||
|
dimensionRef = "A1";
|
||||||
|
else if (maxColumnIndex == 1)
|
||||||
|
dimensionRef = $"A{maxRowIndex}";
|
||||||
|
else
|
||||||
|
dimensionRef = $"A1:{Helpers.GetAlphabetColumnName(maxColumnIndex - 1)}{maxRowIndex}";
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultFiles[@"xl/worksheets/sheet1.xml"].Xml = $@"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||||
|
<x:worksheet xmlns:x=""http://schemas.openxmlformats.org/spreadsheetml/2006/main"">
|
||||||
|
<dimension ref=""{dimensionRef}""/>
|
||||||
|
<x:sheetData>{sb.ToString()}</x:sheetData>
|
||||||
|
</x:worksheet>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultFiles;
|
||||||
|
}
|
||||||
|
private readonly static UTF8Encoding Utf8WithBom = new System.Text.UTF8Encoding(true);
|
||||||
|
|
||||||
|
private static bool IsDapperRowOrDictionaryStringObject(object value)
|
||||||
|
{
|
||||||
|
return value is IEnumerable<IDictionary<string, object>>;
|
||||||
|
}
|
||||||
|
private static void CreteXlsxImpl(Dictionary<string, ZipPackageInfo> zipPackageInfos, ZipArchive archive)
|
||||||
|
{
|
||||||
|
//[Content_Types].xml
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
|
||||||
|
<Types xmlns=""http://schemas.openxmlformats.org/package/2006/content-types"">
|
||||||
|
<Default ContentType=""application/xml"" Extension=""xml""/>
|
||||||
|
<Default ContentType=""application/vnd.openxmlformats-package.relationships+xml"" Extension=""rels""/>");
|
||||||
|
foreach (var p in zipPackageInfos)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"<Override ContentType=\"{p.Value.ContentType}\" PartName=\"/{p.Key}\" />");
|
||||||
|
}
|
||||||
|
sb.AppendLine("</Types>");
|
||||||
|
|
||||||
|
ZipArchiveEntry entry = archive.CreateEntry("[Content_Types].xml");
|
||||||
|
using (var zipStream = entry.Open())
|
||||||
|
using (StreamWriter writer = new StreamWriter(zipStream, Utf8WithBom))
|
||||||
|
writer.Write(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var p in zipPackageInfos)
|
||||||
|
{
|
||||||
|
ZipArchiveEntry entry = archive.CreateEntry(p.Key);
|
||||||
|
using (var zipStream = entry.Open())
|
||||||
|
using (StreamWriter writer = new StreamWriter(zipStream, Utf8WithBom))
|
||||||
|
writer.Write(p.Value.Xml.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -537,19 +537,6 @@ namespace MiniExcelLibs.Tests
|
|||||||
return new SQLiteConnection(connectionString);
|
return new SQLiteConnection(connectionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact()]
|
|
||||||
//public void QueryDapperRows()
|
|
||||||
//{
|
|
||||||
// var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
|
|
||||||
// var connectionString = $"Data Source=:memory:";
|
|
||||||
|
|
||||||
// using (var connection = new SQLiteConnection(connectionString))
|
|
||||||
// {
|
|
||||||
// var rows = connection.Query(@"select 1 A,2 B union all select 3 A,4 B").ToList();
|
|
||||||
// MiniExcel.SaveAs(path, rows);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
[Fact()]
|
[Fact()]
|
||||||
public void SQLiteInsertTest()
|
public void SQLiteInsertTest()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user