c# - Excel 表验证/公式未复制到新表行

标签 c# excel openxml openxml-sdk epplus

我目前正在使用 EPPlus 库将大量数据导出到多个工作表和每个工作表旁边的表格。

我已经能够创建列表验证,并通过名为 range 的查找工作表让它正常工作。但是,我遇到了一些我无法弄清楚的奇怪行为。

开始:

我下载文件。我打开文件。我选择了一个带有表格的电子表格,表格中有多个行,有一个列表验证列,其中选项是/否可从下拉列表中进行选择。每行都有此列表验证。

场景 1:

然后我在 excel 表中创建一个新行,方法是从 excel 表的右下角拖动以创建新行。公式未复制到新行。我现在丢失了对 Excel 表中新行的验证。

场景 2:

我删除了 excel 表中的所有现有行,除了第一行(它仍然包含在是/否列中的列表验证)。然后我通过从 excel 表的右下角拖动来创建新行,从而在 excel 表中创建一个新行。

公式已复制到新行,我现在可以使用提供的验证将新的有效数据插入该行。

我的代码逻辑:

每个单元格都通过一个循环对其应用验证,该循环获取单元格需要的验证类型(即数字、日期、列表、大于、小于等)。列表验证是通过命名的表查找地址访问的。没有 XML 输出错误,文件打开正常,我可以毫无问题地从单元格访问列表验证。

我尝试解决此问题的方法:

1) 填充单元格范围,然后从该范围创建 excel 表格。 - 这背后的想法是,首先创建一系列数据,然后选择范围并将其转换为 Excel 表格。默认行为是表中的新行仅复制上一行的公式。所以这个解决方案似乎合乎逻辑。

2) 在一系列未填充的单元格上创建一个 Excel 表格,然后填充该区域。 - 这背后的想法是,EPPlus 在工作表中创建表格的方式可能存在错误,或者 XML 元素的顺序可能存在问题,实际上只是一个实验性更改。

代码:

   var strategy = Strategy.CreateTableFirst;
   ExcelRange subRowDataRange = null;
   ExcelTable table = null;

   if (strategy == Strategy.CreateTableFirst)
   {
       subRowDataRange = worksheet.Cells[headerRowIndex, worksheet.Dimension.Start.Column, ToRow: headerRowIndex + groupedRowData.Count(), ToCol: dataFields.Count()];
       table = worksheet.Tables.Add(subRowDataRange, Name: null); // Auto generate Excel table name
       table.TableStyle = TableStyles.Light13;  
   }

   foreach (var field in dataFields)
   {
       // Headers
       if (strategy == Strategy.CreateTableFirst)
       {
           table.Columns[dataFields.IndexOf(field)].Name = field.Name;  
       }
       else
       {
           worksheet.Cells[headerRowIndex, columnIndex].Value = field.Name;    
       }

       // Help Text
       if (field.HelpText.HasValue())
       {
           worksheet.Cells[headerRowIndex, columnIndex].AddComment(field.HelpText, Author: "System");
       }

       int dataRowIndex = headerRowIndex + 1; // First row in the datatable

       if (groupedRowData.None())
       {
           worksheet.Cells[dataRowIndex, columnIndex].Set(field, owner: owner, rowIndex: null, addValidation: true);
       }

       // Add SubRows
       foreach (var rowData in groupedRowData)
       {
           worksheet.Cells[dataRowIndex, columnIndex].Set(field, owner: owner, rowIndex: rowData.Key, addValidation: true);
           dataRowIndex++;
       }

       columnIndex++;
   }

   if (strategy == Strategy.CreateTableLast)
   {
       subRowDataRange = worksheet.Cells[headerRowIndex, worksheet.Dimension.Start.Column, ToRow: worksheet.Dimension.End.Row + 1, ToCol: dataFields.Count()];
       table = worksheet.Tables.Add(subRowDataRange, Name: null);
       table.TableStyle = TableStyles.Light13;  
   }

这是代码后excel中的输出表:

Excel Table with Data exported to excel

有趣的是,如果我手动创建表格并将第一行设置为数据,则单元格验证可以很好地复制到下一行,然后向下拖动以创建一个新行并且它可以很好地复制。我不确定我将如何导出多行数据并确保当用户插入新行时,验证会被复制下来。

我下载了 Microsoft XML SDK 来比较具有 1 行的 excel 表(然后我可以向下拖动以使用复制的公式创建第二行)和原始下载的 excel 文件在 excel 表中有许多行。

结果与 XML 输出中的 excel 表几乎相同。

Excel Table Comparison XML

在删除行并保存文件以供比较后,似乎也没有什么不妥之处。

Exported on the right, deleted rows and saved on the left

任何 EPPlus 专家有想法吗?

更新:2015 年 4 月 30 日。客户了解问题并接受它的本来面目。没有找到解决方案。

最佳答案

我不熟悉 EPPlus,但我之前在 VBA 中遇到过这个问题,并且能够通过使用看起来像这样的 VBA 脚本强制填充表格:

LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Range(Cells(TopRowOfTable,ColumnOfTableRow1),Cells(LastRow,ColumnOfTableRow1).Filldown

基本上只是找到最后一行,然后使用 filldown 命令强制填充该字段。

关于c# - Excel 表验证/公式未复制到新表行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25115978/

相关文章:

c# - 在 WinXP 上使用 .NET 的文件系统事务

vba - 浏览工作表的所有对象(表格除外),并打印其类型

excel - 在当前目录中打开工作簿

c# - 使用 Open XML SDK 进行邮件合并

java - OOXML 电子表格中的默认单元格类型

c# - 使用 AutoMapper 和 DI 容器实例化类型

c# - 如何从另一个 Windows 应用程序获取 Chrome 28 的当前 URL?

excel - VBA遍历表

c# - OpenXml:工作表子元素的顺序更改导致文件损坏

c# - 如何将快捷方式(.lnk)包含到解决方案中?