如何在 ClosedXML 中使用渐变填充 (GradientFill)
How to use a gradient fill (GradientFill) with ClosedXML
我正在开发 C#/ASP.NET web 东西,想做一个 Excel 导出。首先我找到了 OpenXML,做了一些第一步,但它真的很难用。现在,我正在使用 ClosedXML,这让我松了一口气 - 到目前为止。
我想到了在 table 单元格上进行渐变填充的问题...像
这样的正常填充没有问题
worksheet.Cell(1,1).Style.Fill.SetBackgroundColor(XLColor.Red);
或者像
这样的模式
worksheet.Cell(1,1).Style.Fill.PatternType = XLFillPatternValues.LightHorizontal;
worksheet.Cell(1,1).Style.Fill.PatternColor = XLColor.Green;
worksheet.Cell(1,1).Style.Fill.PatternBackgroundColor = XLColor.White;
但是GradientFill怎么做呢?据我所知,ClosedXML 是建立在 OpenXML SDK 上的,所以应该可以做一个 GradientFill - 类似的东西(我还不能测试)
GradientFill gFillEx = new GradientFill();
GradientStop gStop1st = new GradientStop();
gStop1st.Position = 0;
gStop1st.Color = new Color { Rgb = HexBinaryValue.FromString("00FF00") };
GradientStop gStop2nd = new GradientStop();
gStop2nd.Position = 1;
gStop2nd.Color = new Color { Rgb = HexBinaryValue.FromString("FFFFFF") };
gFillEx.InsertAt<GradientStop>(gStop1st, 0);
gFillEx.InsertAt<GradientStop>(gStop2nd, 1);
但是如何进行 - 如何将这个 gFillEx 设置为单元格的填充样式?我也不介意直接在此处某处使用 styles.xml 文件中的 xml - 如果我只知道放在哪里。
有什么提示或有用的想法吗?谢谢
在 ClosedXML 不知道 GradientFill 之后,由于我没有找到在 ClosedXML 中操作 OpenXML 的 WorkbookStylesPart 的方法,我最终采用了以下解决方法
首先在内存流中生成你的 .xlsx
public ActionResult XLSX()
{
System.IO.Stream spreadsheetStream = new System.IO.MemoryStream();
XLWorkbook workbook = new XLWorkbook();
IXLWorksheet worksheet = workbook.Worksheets.Add("GradientFillExample");
worksheet.Cell(1, 1).SetValue("example").Style.Fill.SetBackgroundColor(XLColor.FromHtml("#08F47B")); // use some unique color
workbook.SaveAs(spreadsheetStream);
我们的想法是使用一种独特的填充颜色 - 我们将用我们想要的渐变填充替换 WorkbookStylesPart 中的填充...所以我们再次使用 OpenXML 打开内存流(使用内存流,我们不必关心临时文件)并导航到样式表
SpreadsheetDocument package = SpreadsheetDocument.Open(spreadsheetStream, true);
WorkbookPart wbPart = package.GetPartsOfType<WorkbookPart>().FirstOrDefault();
WorkbookStylesPart wbStylePart = wbPart.GetPartsOfType<WorkbookStylesPart>().FirstOrDefault();
Stylesheet stylesheet = wbStylePart.Stylesheet; // all three are not null - check if you want
由于始终有两种默认填充样式,因此样式表永远不会为空。现在我们可以在样式表的填充中搜索我们独特的颜色,并用我们的渐变填充替换该填充
OpenXmlElement oldFill = stylesheet.Fills.FirstOrDefault(f => f.OuterXml.Contains("08F47B")); // find the fill that uses your unique color
if (oldFill != null) // maybe you generate the .xlsx and the "gradient fill" is not always present
{
GradientFill gradientFill = new GradientFill() { Degree = 0 };
gradientFill.Append(new GradientStop() { Position = 0D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 1D, Color = new Color() { Rgb = "FFFFFFFF" } });
oldFill.ReplaceChild(gradientFill, oldFill.FirstChild); // inside the fill replace the patternFill with your gradientFill
}
package.Close();
最后我们可以关闭内存流并提供下载...
spreadsheetStream.Position = 0;
return new FileStreamResult(spreadsheetStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = "gradfillexample.xlsx" };
}
为了进行测试,只需将该操作放入您的控制器中即可。别忘了你需要一些用法:
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using ClosedXML.Excel;
有趣的部分:您还可以使用 0、90、180、270 以外的其他度数(会产生某种对角线渐变),您甚至可以使用多级渐变,所以像这样也可以
GradientFill gradientFill = new GradientFill() { Degree = 354 };
gradientFill.Append(new GradientStop() { Position = 0D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 0.49D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 0.51D, Color = new Color() { Rgb = "FFFFFFFF" } });
gradientFill.Append(new GradientStop() { Position = 1D, Color = new Color() { Rgb = "FFFFFFFF" } });
虽然 Excel(和 Excel Viewer)正确显示了这一点(角度值对应于方形单元格,因此可能会被拉伸),但您无法编辑角度值或Excel 中的多站渐变,不过,它对生成的工作表很好。
我正在开发 C#/ASP.NET web 东西,想做一个 Excel 导出。首先我找到了 OpenXML,做了一些第一步,但它真的很难用。现在,我正在使用 ClosedXML,这让我松了一口气 - 到目前为止。
我想到了在 table 单元格上进行渐变填充的问题...像
这样的正常填充没有问题worksheet.Cell(1,1).Style.Fill.SetBackgroundColor(XLColor.Red);
或者像
这样的模式worksheet.Cell(1,1).Style.Fill.PatternType = XLFillPatternValues.LightHorizontal;
worksheet.Cell(1,1).Style.Fill.PatternColor = XLColor.Green;
worksheet.Cell(1,1).Style.Fill.PatternBackgroundColor = XLColor.White;
但是GradientFill怎么做呢?据我所知,ClosedXML 是建立在 OpenXML SDK 上的,所以应该可以做一个 GradientFill - 类似的东西(我还不能测试)
GradientFill gFillEx = new GradientFill();
GradientStop gStop1st = new GradientStop();
gStop1st.Position = 0;
gStop1st.Color = new Color { Rgb = HexBinaryValue.FromString("00FF00") };
GradientStop gStop2nd = new GradientStop();
gStop2nd.Position = 1;
gStop2nd.Color = new Color { Rgb = HexBinaryValue.FromString("FFFFFF") };
gFillEx.InsertAt<GradientStop>(gStop1st, 0);
gFillEx.InsertAt<GradientStop>(gStop2nd, 1);
但是如何进行 - 如何将这个 gFillEx 设置为单元格的填充样式?我也不介意直接在此处某处使用 styles.xml 文件中的 xml - 如果我只知道放在哪里。
有什么提示或有用的想法吗?谢谢
在 ClosedXML 不知道 GradientFill 之后,由于我没有找到在 ClosedXML 中操作 OpenXML 的 WorkbookStylesPart 的方法,我最终采用了以下解决方法
首先在内存流中生成你的 .xlsx
public ActionResult XLSX()
{
System.IO.Stream spreadsheetStream = new System.IO.MemoryStream();
XLWorkbook workbook = new XLWorkbook();
IXLWorksheet worksheet = workbook.Worksheets.Add("GradientFillExample");
worksheet.Cell(1, 1).SetValue("example").Style.Fill.SetBackgroundColor(XLColor.FromHtml("#08F47B")); // use some unique color
workbook.SaveAs(spreadsheetStream);
我们的想法是使用一种独特的填充颜色 - 我们将用我们想要的渐变填充替换 WorkbookStylesPart 中的填充...所以我们再次使用 OpenXML 打开内存流(使用内存流,我们不必关心临时文件)并导航到样式表
SpreadsheetDocument package = SpreadsheetDocument.Open(spreadsheetStream, true);
WorkbookPart wbPart = package.GetPartsOfType<WorkbookPart>().FirstOrDefault();
WorkbookStylesPart wbStylePart = wbPart.GetPartsOfType<WorkbookStylesPart>().FirstOrDefault();
Stylesheet stylesheet = wbStylePart.Stylesheet; // all three are not null - check if you want
由于始终有两种默认填充样式,因此样式表永远不会为空。现在我们可以在样式表的填充中搜索我们独特的颜色,并用我们的渐变填充替换该填充
OpenXmlElement oldFill = stylesheet.Fills.FirstOrDefault(f => f.OuterXml.Contains("08F47B")); // find the fill that uses your unique color
if (oldFill != null) // maybe you generate the .xlsx and the "gradient fill" is not always present
{
GradientFill gradientFill = new GradientFill() { Degree = 0 };
gradientFill.Append(new GradientStop() { Position = 0D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 1D, Color = new Color() { Rgb = "FFFFFFFF" } });
oldFill.ReplaceChild(gradientFill, oldFill.FirstChild); // inside the fill replace the patternFill with your gradientFill
}
package.Close();
最后我们可以关闭内存流并提供下载...
spreadsheetStream.Position = 0;
return new FileStreamResult(spreadsheetStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = "gradfillexample.xlsx" };
}
为了进行测试,只需将该操作放入您的控制器中即可。别忘了你需要一些用法:
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using ClosedXML.Excel;
有趣的部分:您还可以使用 0、90、180、270 以外的其他度数(会产生某种对角线渐变),您甚至可以使用多级渐变,所以像这样也可以
GradientFill gradientFill = new GradientFill() { Degree = 354 };
gradientFill.Append(new GradientStop() { Position = 0D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 0.49D, Color = new Color() { Rgb = "FF00FF00" } });
gradientFill.Append(new GradientStop() { Position = 0.51D, Color = new Color() { Rgb = "FFFFFFFF" } });
gradientFill.Append(new GradientStop() { Position = 1D, Color = new Color() { Rgb = "FFFFFFFF" } });
虽然 Excel(和 Excel Viewer)正确显示了这一点(角度值对应于方形单元格,因此可能会被拉伸),但您无法编辑角度值或Excel 中的多站渐变,不过,它对生成的工作表很好。