c# EPPlus - 根据行中的条件数据合并 Excel 中的行
c# EPPlus - Merge Rows in Excel based on conditional Data in rows
我正在使用 EPPlus 库创建 Excel 报告。
到目前为止,我已经使用以下代码在 sheet 上加载了 DataTable
:
string FileName = @"DataSource\sampleData.xml";
var excelDocName = @"C:\Excel\OutExcel.xlsx";
var aFile = new FileInfo(excelDocName);
if (File.Exists(excelDocName))
File.Delete(excelDocName);
DataSet ds = new DataSet();
ds.ReadXml(FileName);
DataTable xmlTable = ds.Tables[0];
using (ExcelPackage pck = new ExcelPackage(aFile))
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("DataLoad");
ws.Cells["A1"].LoadFromDataTable(xmlTable, true);
ws.Cells.AutoFitColumns();
pck.Save();
}
结果很完美,但我需要的是
合并 A 列中具有相同值的行,基于此我需要合并 B、C 和 D 列中的行。
根据A列对E列的值范围求和,并合并E列的行并显示求和结果。
我附上了我得到的截图和需要的结果,还分享了 Excel 文件和 XML 数据源以快速使用代码生成 Excel .
根据 'alhashmiya' 的建议,我更改了逻辑并逐行迭代 DataTable 以插入,在插入期间我将特定列保存在变量中以更新合并范围。
以下代码适用于将来有相同需求的任何人,
string FileName = @"DataSource\sampleData.xml";
var excelDocName = @"c:\temp\OutExcel.xlsx";
var aFile = new FileInfo(excelDocName);
DataSet ds = new DataSet();
ds.ReadXml(FileName);
DataTable table = ds.Tables[0];
using (ExcelPackage pck = new ExcelPackage(aFile))
{
ExcelWorksheet ws = pck.Workbook.Worksheets[1];
const int startRow = 2;
int mergestarttrow = 2;
int rw = startRow;
int RefNo = 0;
int TTLCONS = 0;
string[] mergedColNamed = new string[] { "SNO", "_NAME", "CAUSE_SUBCAUSE", "_AREAS", "CONS", "GRIDNAM" };
Dictionary<string, string> mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
if (table.Rows.Count != 0)
{
foreach (DataRow row in table.Rows)
{
bool needMerge = false;
bool checkMerge = false;
//Hold to compare with next iteration and based to condition match Enable Check Merge Flag
int CurrentRefNo = System.Convert.ToInt32(row["SNO"]);
if (RefNo > 0)
{
if (RefNo == CurrentRefNo)
{
checkMerge = true;
mergeRange = mergeRange = mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
}
else
{
mergestarttrow = rw;
needMerge = true;
}
}
int col = 1;
if (rw > startRow)
ws.InsertRow(rw, 1);
if (needMerge)
{
for (int i = 0; i < mergedColNamed.Length; i++)
{
string MergeRangeValue = mergeRange.FirstOrDefault(x => x.Key == mergedColNamed[i]).Value;
using (ExcelRange Rng = ws.Cells[MergeRangeValue])
{
Rng.Merge = true;
ws.Cells[MergeRangeValue].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
ws.Cells[MergeRangeValue].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
Rng.Style.Border.Top.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Left.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Right.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
if (mergedColNamed[i] == "CONS")
{
Rng.Value = TTLCONS;
TTLCONS = 0;
Rng.Style.Numberformat.Format = "0";
}
if (mergedColNamed[i] == "SNO")
{
Rng.Style.Numberformat.Format = "0";
}
}
}
mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
}
foreach (DataColumn dc in table.Columns)
{
if (mergedColNamed.Contains(dc.ColumnName.ToUpper()))
{
if (dc.ColumnName.ToUpper() == "CONS")
TTLCONS = TTLCONS + System.Convert.ToInt32(row[dc]);
if (!checkMerge)//First Row
{
if (dc.ColumnName.ToUpper() == "SNO")
RefNo = System.Convert.ToInt32(row[dc]);
ws.Cells[rw, col].Value = row[dc].ToString();
ws.Cells[rw, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
ws.Cells[rw, col].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
ws.Cells[rw, col].Style.Border.Top.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Left.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Right.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
if (dc.ColumnName.ToUpper() == "CONS")
{
ws.Cells[rw, col].Style.Numberformat.Format = "0";
}
}
else //No Need to set Cell Values as ultimately we will merge only updating the merge range
{
string MergeRangeKey = mergeRange.FirstOrDefault(x => x.Value == mergeRange[dc.ColumnName.ToUpper()]).Key;
string MergeRangeValue = mergeRange[dc.ColumnName.ToUpper()];
mergeRange[MergeRangeKey] = string.Format(mergeRange[dc.ColumnName.ToUpper()] + "{0}:" + mergeRange[dc.ColumnName.ToUpper()] + "{1}", mergestarttrow, rw);
}
}
else
{
ws.Cells[rw, col].Value = row[dc].ToString();
ws.Cells[rw, col].Style.Border.Top.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Left.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Right.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
}
col++;
}
rw++;
}
}
ws.Cells.AutoFitColumns();
pck.Save();
System.Diagnostics.Process.Start(excelDocName);
我正在使用 EPPlus 库创建 Excel 报告。
到目前为止,我已经使用以下代码在 sheet 上加载了 DataTable
:
string FileName = @"DataSource\sampleData.xml";
var excelDocName = @"C:\Excel\OutExcel.xlsx";
var aFile = new FileInfo(excelDocName);
if (File.Exists(excelDocName))
File.Delete(excelDocName);
DataSet ds = new DataSet();
ds.ReadXml(FileName);
DataTable xmlTable = ds.Tables[0];
using (ExcelPackage pck = new ExcelPackage(aFile))
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("DataLoad");
ws.Cells["A1"].LoadFromDataTable(xmlTable, true);
ws.Cells.AutoFitColumns();
pck.Save();
}
结果很完美,但我需要的是
合并 A 列中具有相同值的行,基于此我需要合并 B、C 和 D 列中的行。
根据A列对E列的值范围求和,并合并E列的行并显示求和结果。
我附上了我得到的截图和需要的结果,还分享了 Excel 文件和 XML 数据源以快速使用代码生成 Excel .
根据 'alhashmiya' 的建议,我更改了逻辑并逐行迭代 DataTable 以插入,在插入期间我将特定列保存在变量中以更新合并范围。
以下代码适用于将来有相同需求的任何人,
string FileName = @"DataSource\sampleData.xml";
var excelDocName = @"c:\temp\OutExcel.xlsx";
var aFile = new FileInfo(excelDocName);
DataSet ds = new DataSet();
ds.ReadXml(FileName);
DataTable table = ds.Tables[0];
using (ExcelPackage pck = new ExcelPackage(aFile))
{
ExcelWorksheet ws = pck.Workbook.Worksheets[1];
const int startRow = 2;
int mergestarttrow = 2;
int rw = startRow;
int RefNo = 0;
int TTLCONS = 0;
string[] mergedColNamed = new string[] { "SNO", "_NAME", "CAUSE_SUBCAUSE", "_AREAS", "CONS", "GRIDNAM" };
Dictionary<string, string> mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
if (table.Rows.Count != 0)
{
foreach (DataRow row in table.Rows)
{
bool needMerge = false;
bool checkMerge = false;
//Hold to compare with next iteration and based to condition match Enable Check Merge Flag
int CurrentRefNo = System.Convert.ToInt32(row["SNO"]);
if (RefNo > 0)
{
if (RefNo == CurrentRefNo)
{
checkMerge = true;
mergeRange = mergeRange = mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
}
else
{
mergestarttrow = rw;
needMerge = true;
}
}
int col = 1;
if (rw > startRow)
ws.InsertRow(rw, 1);
if (needMerge)
{
for (int i = 0; i < mergedColNamed.Length; i++)
{
string MergeRangeValue = mergeRange.FirstOrDefault(x => x.Key == mergedColNamed[i]).Value;
using (ExcelRange Rng = ws.Cells[MergeRangeValue])
{
Rng.Merge = true;
ws.Cells[MergeRangeValue].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
ws.Cells[MergeRangeValue].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
Rng.Style.Border.Top.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Left.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Right.Style = ExcelBorderStyle.Thin;
Rng.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
if (mergedColNamed[i] == "CONS")
{
Rng.Value = TTLCONS;
TTLCONS = 0;
Rng.Style.Numberformat.Format = "0";
}
if (mergedColNamed[i] == "SNO")
{
Rng.Style.Numberformat.Format = "0";
}
}
}
mergeRange = new Dictionary<string, string>() { { "SNO", "A" }, { "_NAME", "B" }, { "CAUSE_SUBCAUSE", "C" }, { "_AREAS", "D" }, { "CONS", "E" }, { "GRIDNAM", "F" } };
}
foreach (DataColumn dc in table.Columns)
{
if (mergedColNamed.Contains(dc.ColumnName.ToUpper()))
{
if (dc.ColumnName.ToUpper() == "CONS")
TTLCONS = TTLCONS + System.Convert.ToInt32(row[dc]);
if (!checkMerge)//First Row
{
if (dc.ColumnName.ToUpper() == "SNO")
RefNo = System.Convert.ToInt32(row[dc]);
ws.Cells[rw, col].Value = row[dc].ToString();
ws.Cells[rw, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
ws.Cells[rw, col].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
ws.Cells[rw, col].Style.Border.Top.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Left.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Right.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
if (dc.ColumnName.ToUpper() == "CONS")
{
ws.Cells[rw, col].Style.Numberformat.Format = "0";
}
}
else //No Need to set Cell Values as ultimately we will merge only updating the merge range
{
string MergeRangeKey = mergeRange.FirstOrDefault(x => x.Value == mergeRange[dc.ColumnName.ToUpper()]).Key;
string MergeRangeValue = mergeRange[dc.ColumnName.ToUpper()];
mergeRange[MergeRangeKey] = string.Format(mergeRange[dc.ColumnName.ToUpper()] + "{0}:" + mergeRange[dc.ColumnName.ToUpper()] + "{1}", mergestarttrow, rw);
}
}
else
{
ws.Cells[rw, col].Value = row[dc].ToString();
ws.Cells[rw, col].Style.Border.Top.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Left.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Right.Style = ExcelBorderStyle.Thin;
ws.Cells[rw, col].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
}
col++;
}
rw++;
}
}
ws.Cells.AutoFitColumns();
pck.Save();
System.Diagnostics.Process.Start(excelDocName);