[C#] 解决使用ClosedXML生成Excel报表丢失样式的两种方法
使用ClosedXML生成excel前, 如果在excel的template中提前设置好样式, 比如单元格颜色, 自动回行等, 之后再使用ClosedXML写入数据的时候会出现样式丢失的情况; 还有一种情况, 在已经设置好的样式excel中写入数据的时候, 发现第一样永远不会折行, 而从datatable的第二行开始写就没有问题.
解决办法: 样式丢失的问题尤其是第一行样式被覆盖的情况,不确定是不是其本身机制就是被覆盖掉了还是其实是ClosedXML的bug, 最后总结了两种曲线救国的办法(参考下面), 整体思路是复制已经设置好的报表格式的某一行, 之后copy到真正应该写入数据的行中, 之后再写入数据; 另一种是先写入数据, 之后再将base表格的样式copy到整体的数据行中.
方法1:
public byte[] ExportReport(Report obj)
{
var result = _repository.GetRegisteredNum(obj);
//copy a new file named with time
string nowTimeStamp = GetTimeStamp();
string basePath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string path = basePath + Common.Constants.Template.LocalPath;
string sourceFile = path + "ReportTemplate.xlsx";
string destinationFile = sourceFile + nowTimeStamp + ".xlsx";
File.Copy(sourceFile, destinationFile, false);
string[] reportColumn = {"B", "C", "D", "E"};
using (XLWorkbook wb = new XLWorkbook(destinationFile))
{
var ws = wb.Worksheet(1);
int rowindex = 1;
//foreach (var result in obj.OutstandingOLList)
foreach (var resulta in result)
{
int row = 15 + result.IndexOf(resulta);
var copyRows = ws.Row(13).AsRange(); // Always copy row 13 style to others row.
var copyToRows = ws.Row(row).AsRange();
copyRows.CopyTo(copyToRows);
ws.Cell(row, "A").Value = rowindex++ ;
ws.Cell(row, reportColumn[0]).Value = resulta.AValue;
ws.Cell(row, reportColumn[1]).Value = resulta.BValue;
ws.Cell(row, reportColumn[2]).Value = resulta.CValue;
ws.Cell(row, reportColumn[3]).Value = resulta.DValue;
}
// delete origin row 13.
ws.Row(13).Delete();
using (var ms = new MemoryStream())
{
wb.SaveAs(ms);
File.Delete(destinationFile);
return ms.ToArray();
}
}
}
方法2:
public byte[] ExportReport2(Report obj)
{
var result = _repository.GetRegisteredNum(obj);
//copy a new file named with time
string nowTimeStamp = GetTimeStamp();
string basePath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string path = basePath + Common.Constants.Template.LocalPath;
string sourceFile = path + "ReportTemplate.xlsx";
string destinationFile = sourceFile + nowTimeStamp + ".xlsx";
File.Copy(sourceFile, destinationFile, false);
string[] reportColumn = {"B", "C", "D", "E"};
using (XLWorkbook wb = new XLWorkbook(destinationFile))
{
var ws = wb.Worksheet(1);
int rowindex = 1;
//foreach (var result in obj.OutstandingOLList)
foreach (var resulta in result)
{
int row = 15 + result.IndexOf(resulta);
// var copyRows = ws.Row(13).AsRange(); // Always copy row 13 style to others row.
// var copyToRows = ws.Row(row).AsRange();
copyRows.CopyTo(copyToRows);
ws.Cell(row, "A").Value = rowindex++ ;
ws.Cell(row, reportColumn[0]).Value = resulta.AValue;
ws.Cell(row, reportColumn[1]).Value = resulta.BValue;
ws.Cell(row, reportColumn[2]).Value = resulta.CValue;
ws.Cell(row, reportColumn[3]).Value = resulta.DValue;
for (int m = 0; m < 6; m++){
// copy row 13 style to others row by 1 cell.
ws.Cell(row, reportColumn[m]).Style = ws.Cell(13 , reportColumn[m]).Style;
}
}
// delete origin row 13.
ws.Row(13).Delete();
using (var ms = new MemoryStream())
{
wb.SaveAs(ms);
File.Delete(destinationFile);
return ms.ToArray();
}
}
}
其他说明:
No.1 在上述代码中都有删除base line的代码操作(ws.Row(13).Delete();) , 如果是要删除多行可能会出现OutOfMemory errors, 或者删除不掉行的情况
解决办法:
Turning off events
By default ClosedXML keeps track of the inserts/deletes and adjusts the ranges accordingly.
For example:
var testRow = worksheet.Row(1);
worksheet.Row(1).InsertRowsAbove(1);
// testRow now points to the second row of the worksheet, not the first.
If you don't need this feature then you can turn it off to save memory and increase performance. Just open your workbook with the option XLEventTracking.Disabled.
var wb = new XLWorkbook(XLEventTracking.Disabled);
No.2 发生 Could not load file or assembly 'DocumentFormat.OpenXml' 异常
解决办法:
https://stackoverflow.com/questions/25307323/could-not-load-file-or-assembly-documentformat-openxml
https://www.microsoft.com/en-us/download/details.aspx?id=5124
除了版本问题外, 也要考虑是否在deploy的时候丢失了该类库.
注:本文原创由`bluetata`发布于blog.csdn.net、转载请务必注明出处。
相关文章
- C#.NET将数组导入Excel源代码
- C# 将Excel转换为PDF
- C#异步编程一
- 《ASP.NET1200例》C#在网页上编写动态时钟
- C#.NET常见问题(FAQ)-如何使用DataGridView跟Excel数据交互
- 【C#】Excel导出合并行和列并动态加载行与列
- C#.net word excel powerpoint (ppt) 转换成 pdf 文件
- [压缩]C#下使用SevenZipSharp压缩解压文本
- 在C#代码中应用Log4Net(一)简单使用Log4Net
- C#.net word excel powerpoint (ppt) 转换成 pdf 文件
- C# 直接调用非托管代码的方法
- 重新整理数据结构与算法(c#)—— 堆排序[二十一]
- C# 获取Excel工作薄中Sheet页(工作表)名集合
- C# Excel数据验重及Table数据验重
- C# chart,有关如何在鼠标移动到Series上时显示节点及数据 (有待继续更新)
- C#操作Excel,对Sheet插入次序的控制 (有待完善)
- [转] C#操作Excel文件
- C# 对Excel文档打印时的页面设置
- [转] 从数据库中读取图片并导入Excel文件,C#方式
- C# 可以利用反射给只读属性赋值吗?
- C# 获取Excel工作薄中Sheet页(工作表)名集合
- C# string格式的日期时间字符串转为DateTime类型
- Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持
- 〖Python自动化办公篇⑫〗- Excel 文件自动化 - 读取 excel 数据
- c#: using Microsoft.Office.Interop.Excel 异常
- C#界面里的winform BackColor和BackgroundImage属性
- (48)C#空值的条件访问操作符
- C#读取excel文件到datatable
- C# 和Dos窗口的交互
- C# 内存机制 - 基础篇
- C# 中的反射机制
- c++与c#混合编程
- 前端必备技能知识:JS导出Blob流文件为Excel表格、Vue.js使用Blob的方式实现excel表格的下载(流文件下载)
- JAVA操作Excel表格:方法二:POI的使用:Excel实战之POI创建excel文件(高版本.xlsx)
- JAVA操作Excel表格:方法一:jxl的使用②:Excel实战之JXL解析读取excel文件
- 〖Python自动化办公篇⑫〗- Excel 文件自动化 - 读取 excel 数据
- [C#] 解决使用ClosedXML生成Excel报表丢失样式的两种方法