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
| |