I'm working on a C#/ASP.NET web thing and want to do an Excel export. First I found OpenXML, made some first steps, but it's really hard to use. Now, I'm using ClosedXML and it's quite a relief - so far.
I came up with the problem to have a gradient fill on a table cell ... no problem with normal fills like
worksheet.Cell(1,1).Style.Fill.SetBackgroundColor(XLColor.Red);
or with Patterns like
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;
But how to do a GradientFill? As far as I understand ClosedXML is built on the OpenXML SDK, so it should be possible to do a GradientFill - something like (I couldn't test that yet)
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);
But how to proceed - how to set this gFillEx as fill style of a cell? I also wouldn't mind to use the xml from the styles.xml file directly somewhere here - if I only knew where to put.
Any hints or helpful ideas? Thanks.
After ClosedXML doesn't know about GradientFill and as I didn't found a way to manipulate the WorkbookStylesPart of OpenXML within ClosedXML, I ended up with the following workaround
First generate your .xlsx in a memory stream
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);
The idea is to use a unique fill color - we're going to replace that fill in the WorkbookStylesPart with the gradient fill that we intended to have ... so we open the memory stream with OpenXML again (with the memory stream we don't have to care about a temporary file) and navigate to the stylesheet
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
As there are always two default fill styles, the stylesheet's never empty. Now we can search for our unique color in the Fills of the Stylesheet and replace that fill with our gradient fill
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();
Finally we can close the memory stream and present it for download ...
spreadsheetStream.Position = 0;
return new FileStreamResult(spreadsheetStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = "gradfillexample.xlsx" };
}
For testing, simply put that action into your controller. Don't forget you need some usings:
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using ClosedXML.Excel;
The fun part of this: you can also use other degrees than 0, 90, 180, 270 (will result in some kind of diagonal gradient) and you can even use multi-stop gradients, so something like this is also possible
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" } });
While Excel (and Excel Viewer) displays this correctly (the degree value corresponds to a square cell, so that one might be stretched), you can't edit the degree values or multi-stop gradients in Excel, nevertheless, it's nice for generated sheets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With