From cbbc2bc5c42206686e882abfb32096670e00a6ba Mon Sep 17 00:00:00 2001 From: syneffort Date: Tue, 12 Mar 2024 16:46:11 +0900 Subject: [PATCH] Excel helper --- PLibs/ExcelHelper/ExcelHelper.cs | 122 +++++++++++++++++++ PLibs/ExcelHelper/ExcelHelper.csproj | 58 +++++++++ PLibs/ExcelHelper/Properties/AssemblyInfo.cs | 36 ++++++ PLibs/ExcelHelper/packages.config | 5 + PLibs/ExcelHelperCore/ExcelHelper.cs | 115 +++++++++++++++++ PLibs/ExcelHelperCore/ExcelHelperCore.csproj | 13 ++ PLibs/PLibs.sln | 31 +++++ 7 files changed, 380 insertions(+) create mode 100644 PLibs/ExcelHelper/ExcelHelper.cs create mode 100644 PLibs/ExcelHelper/ExcelHelper.csproj create mode 100644 PLibs/ExcelHelper/Properties/AssemblyInfo.cs create mode 100644 PLibs/ExcelHelper/packages.config create mode 100644 PLibs/ExcelHelperCore/ExcelHelper.cs create mode 100644 PLibs/ExcelHelperCore/ExcelHelperCore.csproj create mode 100644 PLibs/PLibs.sln diff --git a/PLibs/ExcelHelper/ExcelHelper.cs b/PLibs/ExcelHelper/ExcelHelper.cs new file mode 100644 index 0000000..baf67eb --- /dev/null +++ b/PLibs/ExcelHelper/ExcelHelper.cs @@ -0,0 +1,122 @@ +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace ExcelHelper +{ + public class ExcelHelper + { + private static readonly ExcelHelper _instance = new ExcelHelper(); + + public static ExcelHelper Instance { get { return _instance; } } + + /// + /// Get excel data + /// + /// excel path + /// sheet name + /// row start position (first row = 1) + /// copy path + /// + /// + public List> GetData(string sourcePath, string sheetName, bool removeHeader, int rowStartPosition = 1, Func, bool> continueFunc = null, string tempPath = "./temp_file.xlsx") + { + File.Copy(sourcePath, tempPath, true); + + List> data = new List>(); + + StringBuilder sb = new StringBuilder(); + using (SpreadsheetDocument doc = SpreadsheetDocument.Open(tempPath, true)) + { + WorkbookPart workbookPart = doc.WorkbookPart; + Sheet sheet = workbookPart.Workbook.Descendants().FirstOrDefault(s => s.Name == sheetName); + + if (sheet == null) + throw new Exception($"Cannot find sheet. (Sheet name: {sheetName})"); + + WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id); + Worksheet worksheet = worksheetPart.Worksheet; + + List rows = worksheet.Descendants().Where(r => r.RowIndex >= rowStartPosition).ToList(); + if (removeHeader) + rows.RemoveAt(0); + + for (int i = 0; i < rows.Count; i++) + { + Dictionary rowPairs = RowToKeyValuePairs(rows[i], workbookPart); + if (rowPairs == null || rowPairs.Count < 1) + continue; + + if (continueFunc != null && continueFunc(rowPairs)) + continue; + + data.Add(rowPairs); + } + } + + return data; + } + + private Dictionary RowToKeyValuePairs(Row row, WorkbookPart workbookPart) + { + Dictionary pairs = new Dictionary(); + var cells = row.Elements().ToList(); + + for (int col = 0; col < cells.Count; col++) + { + Cell cell = cells[col]; + + string cellReference = cell.CellReference.Value; + string columnName = Regex.Replace(cellReference, @"\d", ""); + //int rowNumber = int.Parse(Regex.Replace(cellReference, "[^0-9]", "")); + + string cellValue = cell.CellValue?.InnerText; + if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString) + { + int.TryParse(cellValue, out int sharedStringId); + cellValue = workbookPart.SharedStringTablePart.SharedStringTable.Elements().ElementAt(sharedStringId).InnerText; + } + + pairs.Add(columnName, cellValue); + } + + return pairs; + } + + public string ConvertValue(Dictionary pairs, string key) + { + if (!pairs.ContainsKey(key)) + return null; + + return pairs[key]; + } + + public T ConvertValue(Dictionary pairs, string key, Func func) + { + if (!pairs.ContainsKey(key) || func == null) + return default(T); + + string value = pairs[key]; + return func(value); + } + + public DateTime? ConvertValueToDateTime(Dictionary pairs, string key) + { + return ConvertValue(pairs, key, x => + { + if (string.IsNullOrEmpty(x)) + return null; + + if (double.TryParse(x, out double d)) + return DateTime.FromOADate(d); + else + return null; + }); + } + } +} diff --git a/PLibs/ExcelHelper/ExcelHelper.csproj b/PLibs/ExcelHelper/ExcelHelper.csproj new file mode 100644 index 0000000..6150c28 --- /dev/null +++ b/PLibs/ExcelHelper/ExcelHelper.csproj @@ -0,0 +1,58 @@ + + + + + Debug + AnyCPU + {FFEDB9F8-4285-493B-A30E-900C53D0CB55} + Library + Properties + ExcelHelper + ExcelHelper + v4.5 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\DocumentFormat.OpenXml.3.0.1\lib\net40\DocumentFormat.OpenXml.dll + + + ..\packages\DocumentFormat.OpenXml.Framework.3.0.1\lib\net40\DocumentFormat.OpenXml.Framework.dll + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PLibs/ExcelHelper/Properties/AssemblyInfo.cs b/PLibs/ExcelHelper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..29246c2 --- /dev/null +++ b/PLibs/ExcelHelper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 +// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 +// 이러한 특성 값을 변경하세요. +[assembly: AssemblyTitle("ExcelHelper")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ExcelHelper")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. +[assembly: ComVisible(false)] + +// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. +[assembly: Guid("ffedb9f8-4285-493b-a30e-900c53d0cb55")] + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 +// 기본값으로 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PLibs/ExcelHelper/packages.config b/PLibs/ExcelHelper/packages.config new file mode 100644 index 0000000..097cb68 --- /dev/null +++ b/PLibs/ExcelHelper/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/PLibs/ExcelHelperCore/ExcelHelper.cs b/PLibs/ExcelHelperCore/ExcelHelper.cs new file mode 100644 index 0000000..b4c6715 --- /dev/null +++ b/PLibs/ExcelHelperCore/ExcelHelper.cs @@ -0,0 +1,115 @@ +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; +using System.Text.RegularExpressions; +using System.Text; + +namespace ExcelHelperCore +{ + public class ExcelHelper + { + private static readonly ExcelHelper _instance = new ExcelHelper(); + + public static ExcelHelper Instance { get { return _instance; } } + + /// + /// Get excel data + /// + /// excel path + /// sheet name + /// row start position (first row = 1) + /// copy path + /// + /// + public List> GetData(string sourcePath, string sheetName, bool removeHeader, int rowStartPosition = 1, string tempPath = "./temp_file.xlsx") + { + File.Copy(sourcePath, tempPath, true); + + List> data = new List>(); + + StringBuilder sb = new StringBuilder(); + using (SpreadsheetDocument doc = SpreadsheetDocument.Open(tempPath, true)) + { + WorkbookPart workbookPart = doc.WorkbookPart; + Sheet sheet = workbookPart.Workbook.Descendants().FirstOrDefault(s => s.Name == sheetName); + + if (sheet == null) + throw new Exception("Cannot find sheet."); + + WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id); + Worksheet worksheet = worksheetPart.Worksheet; + + List rows = worksheet.Descendants().Where(r => r.RowIndex >= rowStartPosition).ToList(); + if (removeHeader) + rows.RemoveAt(0); + + for (int i = 0; i < rows.Count; i++) + { + Dictionary rowPairs = RowToKeyValuePairs(rows[i], workbookPart); + if (rowPairs == null || rowPairs.Count < 1) + continue; + + data.Add(rowPairs); + } + } + + return data; + } + + private Dictionary RowToKeyValuePairs(Row row, WorkbookPart workbookPart) + { + Dictionary pairs = new Dictionary(); + var cells = row.Elements().ToList(); + + for (int col = 0; col < cells.Count; col++) + { + Cell cell = cells[col]; + + string cellReference = cell.CellReference.Value; + string columnName = Regex.Replace(cellReference, @"\d", ""); + //int rowNumber = int.Parse(Regex.Replace(cellReference, "[^0-9]", "")); + + string cellValue = cell.CellValue?.InnerText; + if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString) + { + int.TryParse(cellValue, out int sharedStringId); + cellValue = workbookPart.SharedStringTablePart.SharedStringTable.Elements().ElementAt(sharedStringId).InnerText; + } + + pairs.Add(columnName, cellValue); + } + + return pairs; + } + + public string ConvertValue(Dictionary pairs, string key) + { + if (!pairs.ContainsKey(key)) + return null; + + return pairs[key]; + } + + public T ConvertValue(Dictionary pairs, string key, Func func) + { + if (!pairs.ContainsKey(key) || func == null) + return default(T); + + string value = pairs[key]; + return func(value); + } + + public DateTime? ConvertValueToDateTime(Dictionary pairs, string key) + { + return ConvertValue(pairs, key, x => + { + if (string.IsNullOrEmpty(x)) + return null; + + if (double.TryParse(x, out double d)) + return DateTime.FromOADate(d); + else + return null; + }); + } + } +} diff --git a/PLibs/ExcelHelperCore/ExcelHelperCore.csproj b/PLibs/ExcelHelperCore/ExcelHelperCore.csproj new file mode 100644 index 0000000..8edc89c --- /dev/null +++ b/PLibs/ExcelHelperCore/ExcelHelperCore.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/PLibs/PLibs.sln b/PLibs/PLibs.sln new file mode 100644 index 0000000..f9fe5ad --- /dev/null +++ b/PLibs/PLibs.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34511.84 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelHelper", "ExcelHelper\ExcelHelper.csproj", "{FFEDB9F8-4285-493B-A30E-900C53D0CB55}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelHelperCore", "ExcelHelperCore\ExcelHelperCore.csproj", "{0DC75403-4084-462B-936B-FA86EA90811B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FFEDB9F8-4285-493B-A30E-900C53D0CB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FFEDB9F8-4285-493B-A30E-900C53D0CB55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFEDB9F8-4285-493B-A30E-900C53D0CB55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FFEDB9F8-4285-493B-A30E-900C53D0CB55}.Release|Any CPU.Build.0 = Release|Any CPU + {0DC75403-4084-462B-936B-FA86EA90811B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DC75403-4084-462B-936B-FA86EA90811B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DC75403-4084-462B-936B-FA86EA90811B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DC75403-4084-462B-936B-FA86EA90811B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3B2E5C38-A49D-48ED-8CA3-7FBB06E93B60} + EndGlobalSection +EndGlobal