using System;
using System.IO;
using System.Linq;
using System.Xml;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace Neo.Afx.Services.Documents
{
public partial class DocumentUtilities
{
#region GenerateXlsxFromXmlV3
///
/// Generates the XLSX from XML.
///
/// The memory stream to write to.
/// The data in XML format.
public void GenerateXlsxFromXmlV3(MemoryStream ms, XmlDocument data)
{
SpreadsheetDocument spreadSheet = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);
WorkbookPart workbookPart = spreadSheet.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
spreadSheet.WorkbookPart.Workbook.AppendChild(new FileVersion
{
ApplicationName = "Microsoft Office Excel"
});
WorksheetPart worksheetPart = workbookPart.AddNewPart();
worksheetPart.Worksheet = new Worksheet(new SheetData());
WorkbookStylesPart workbookStylesPart = workbookPart.AddNewPart();
workbookStylesPart.Stylesheet = CreateStylesheetV3();
workbookStylesPart.Stylesheet.Save();
Sheets sheets = spreadSheet.WorkbookPart.Workbook.AppendChild(new Sheets());
Sheet sheet = new Sheet
{
Id = spreadSheet.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = _database.GetSysSetting("ExcelExportDefaultSheetName")
};
sheets.Append(sheet);
#region Columns
var columns = data.FirstChild.ChildNodes[0].ChildNodes.Count;
for (var item = 0; item <= columns-1; item++)
{
try
{
SetColumnWidth(worksheetPart.Worksheet, (UInt32)item+1, Convert.ToDouble(data.FirstChild.ChildNodes[0].ChildNodes[item].Attributes["colWidth"].Value));
}
catch (Exception ex)
{
SetColumnWidth(worksheetPart.Worksheet, (UInt32)item + 1, Convert.ToDouble(_database.GetSysSetting("ExcelExportDefaultColumnValue")));
}
}
#endregion
#region SharedStringTablePart
// Get the SharedStringTablePart. If it does not exist, create a new one.
var shareStringPart = spreadSheet.WorkbookPart.GetPartsOfType().Any() ? spreadSheet.WorkbookPart.GetPartsOfType().First() : spreadSheet.WorkbookPart.AddNewPart();
#endregion
#region Insert Data
var rowIndex = (uint)1;
var cellIndex = "A";
var cellCount = 1; //keep count so we can correctly filter heading and not have to many columns
//do header record
foreach (XmlNode childNode in data.FirstChild.ChildNodes[0])
{
var Rowtype = 1;
try
{
InsertCellInWorksheetV3(cellIndex, rowIndex, childNode.InnerText, 1U, worksheetPart, shareStringPart, Rowtype, data.FirstChild.ChildNodes[0].Attributes["rowHeight"].Value);
}
catch (Exception ex)
{
InsertCellInWorksheetV3(cellIndex, rowIndex, childNode.InnerText, 1U, worksheetPart, shareStringPart, Rowtype, _database.GetSysSetting("ExcelExportRowHeight"));
}
if (cellCount < data.FirstChild.ChildNodes[0].ChildNodes.Count)
{
cellIndex = IncrementColRefV3(cellIndex);
cellCount++;
}
}
//filter first row
var autoFilter = new AutoFilter
{
Reference = "A1:" + cellIndex + rowIndex
};
worksheetPart.Worksheet.Append(autoFilter);
//do row records
foreach (XmlNode childNode in data.FirstChild.ChildNodes[1])
{
rowIndex++;
cellIndex = "A";
var styleIndex = rowIndex % 2 == 0 ? 2U : 3U;
foreach (XmlNode cells in childNode.ChildNodes)
{
var RowType = 0;
try
{
InsertCellInWorksheetV3(cellIndex, rowIndex, cells.InnerText, styleIndex, worksheetPart, shareStringPart, RowType, childNode.Attributes["rowHeight"].Value);
}
catch (Exception ex)
{
InsertCellInWorksheetV3(cellIndex, rowIndex, cells.InnerText, styleIndex, worksheetPart, shareStringPart, RowType, _database.GetSysSetting("ExcelExportRowHeight"));
}
cellIndex = IncrementColRefV3(cellIndex);
}
}
#endregion
spreadSheet.WorkbookPart.Workbook.Save();
spreadSheet.Close();
}
#endregion
#region IncrementColRefV3
internal string IncrementColRefV3(string lastRef)
{
var characters = lastRef.ToUpperInvariant().ToCharArray();
var sum = 0;
foreach (var t in characters)
{
sum *= 26;
sum += (t - 'A' + 1);
}
sum++;
var columnName = String.Empty;
while (sum > 0)
{
var modulo = (sum - 1) % 26;
columnName = Convert.ToChar(65 + modulo) + columnName;
sum = ((sum - modulo) / 26);
}
return columnName;
}
#endregion
#region InsertCellInWorksheetV3
internal void InsertCellInWorksheetV3(string columnName, uint rowIndex, string cellValue, uint styleIndex, WorksheetPart worksheetPart, SharedStringTablePart shareStringPart, int RowType,string rowHeight)
{
var worksheet = worksheetPart.Worksheet;
var sheetData = worksheet.GetFirstChild();
var cellReference = columnName + rowIndex;
var row = new Row();
if (sheetData.Elements().Count(r => r.RowIndex.Value == rowIndex) != 0)
{
row = sheetData.Elements().First(r => r.RowIndex.Value == rowIndex);
}
else
{
row.RowIndex = Convert.ToUInt32(rowIndex);
sheetData.Append(row);
}
row.Height = (DoubleValue)Convert.ToDouble(rowHeight);
row.CustomHeight = true;
var cell = new Cell
{
StyleIndex = styleIndex
};
if (row.Elements().Any(c => c.CellReference.Value == cellReference))
{
cell = row.Elements| ().First(c => c.CellReference.Value == cellReference);
}
else
{
cell.CellReference = cellReference;
row.Append(cell);
}
var index = InsertSharedStringItemV3(cellValue, shareStringPart);
cell.DataType = new EnumValue(CellValues.SharedString);
cell.CellValue = new CellValue(index.ToString());
worksheet.Save();
}
#endregion
#region InsertSharedStringItemV3
// Given text and a SharedStringTablePart, creates a SharedStringItem with the specified text
// and inserts it into the SharedStringTablePart. If the item already exists, returns its index.
internal int InsertSharedStringItemV3(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
if (shareStringPart.SharedStringTable == null)
{
shareStringPart.SharedStringTable = new SharedStringTable();
}
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(text)));
shareStringPart.SharedStringTable.Save();
return i;
}
#endregion
#region CreateStylesheet - New
internal Stylesheet CreateStylesheetV3()
{
var stylesheet = new Stylesheet
{
MCAttributes = new MarkupCompatibilityAttributes
{
Ignorable = "x14ac"
}
};
stylesheet.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
stylesheet.AddNamespaceDeclaration("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
#region Fonts
var fonts = new Fonts
{
Count = 2U,
KnownFonts = true
};
var headerFont = new Font
{
FontSize = new FontSize
{
Val = (DoubleValue)Convert.ToDouble(_database.GetSysSetting("ExcelExportHeaderFontHeight"))
},
Bold = new Bold()
{
Val = true
},
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportHeaderFG")
},
FontName = new FontName
{
Val = _database.GetSysSetting("ExcelExportHeaderFontStyle")
}
};
var mainFont = new Font
{
FontSize = new FontSize
{
Val = (DoubleValue)Convert.ToDouble(_database.GetSysSetting("ExcelExportRowFontHeight"))
},
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportCellFG")
},
FontName = new FontName
{
Val = _database.GetSysSetting("ExcelExportRowFontStyle")
}
};
fonts.Append(headerFont);
fonts.Append(mainFont);
#endregion
#region Fills
var fills = new Fills
{
Count = 5U
};
#region generalFill = 0, none
var generalFill = new Fill();
var generalFillPattern = new PatternFill
{
PatternType = PatternValues.None
};
generalFill.Append(generalFillPattern);
#endregion
#region grayFill = 1, none
var grayFill = new Fill();
var grayFillPattern = new PatternFill
{
PatternType = PatternValues.Gray125
};
grayFill.Append(grayFillPattern);
#endregion
#region headerFill = 2, Blue Header
var headerFill = new Fill();
var headerFillPattern = new PatternFill
{
PatternType = PatternValues.Solid
};
var headerForegroundColor = new ForegroundColor
{
Rgb = _database.GetSysSetting("ExcelExportHeaderBG")
};
headerFillPattern.Append(headerForegroundColor);
headerFill.Append(headerFillPattern);
#endregion
#region rowFill = 3, Light blue row
var rowFill = new Fill();
var rowFillPattern = new PatternFill
{
PatternType = PatternValues.Solid
};
var rowForegroundColor = new ForegroundColor
{
Rgb = _database.GetSysSetting("ExcelExportRowBG")
};
var rowBackgroundColor = new BackgroundColor
{
Indexed = 64U
};
rowFillPattern.Append(rowForegroundColor);
rowFillPattern.Append(rowBackgroundColor);
rowFill.Append(rowFillPattern);
#endregion
#region alternateFill = 4, white alternate
var alternateFill = new Fill();
var alternateFillPattern = new PatternFill
{
PatternType = PatternValues.Solid
};
var alternateForegroundColor = new ForegroundColor
{
Rgb = _database.GetSysSetting("ExcelExportRowAlt")
};
var alternateBackgroundColor = new BackgroundColor
{
Indexed = 64U
};
alternateFillPattern.Append(alternateForegroundColor);
alternateFillPattern.Append(alternateBackgroundColor);
alternateFill.Append(alternateFillPattern);
#endregion
fills.Append(generalFill);
fills.Append(grayFill);
fills.Append(headerFill);
fills.Append(rowFill);
fills.Append(alternateFill);
#endregion
#region Borders
var borders = new Borders
{
Count = 2U
};
var noBorder = new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
};
var TotalBorder = new Border
{
LeftBorder = new LeftBorder()
{
Style = BorderStyleValues.Thin,
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportRowBottomBorder")
}
},
RightBorder = new RightBorder()
{
Style = BorderStyleValues.Thin,
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportRowBottomBorder")
}
},
TopBorder = new TopBorder()
{
Style = BorderStyleValues.Thin,
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportRowBottomBorder")
}
},
BottomBorder = new BottomBorder
{
Style = BorderStyleValues.Thin,
Color = new Color
{
Rgb = _database.GetSysSetting("ExcelExportRowBottomBorder")
}
},
DiagonalBorder = new DiagonalBorder()
};
borders.Append(noBorder);
borders.Append(TotalBorder);
#endregion
#region Cell Formatting
#region CellStyleFormats
var cellStyleFormats = new CellStyleFormats
{
Count = 1U
};
var cellFormat = new CellFormat
{
NumberFormatId = 0U,
FontId = 1U,
FillId = 0U,
BorderId = 0U
};
cellStyleFormats.Append(cellFormat);
#endregion
#region CellFormats
var cellFormats = new CellFormats
{
Count = 4U
};
var generalFormat = new CellFormat
{
NumberFormatId = 0U,
FontId = 1U,
FillId = 0U,
BorderId = 0U,
FormatId = 0U
};
var headerFormat = new CellFormat
{
NumberFormatId = 0U,
FontId = 0U,
FillId = 2U,
BorderId = 0U,
FormatId = 0U,
ApplyFill = true
};
var rowFormat = new CellFormat
{
NumberFormatId = 0U,
FontId = 1U,
FillId = 3U,
BorderId = 1U,
FormatId = 0U,
ApplyFill = true
};
var alternateFormat = new CellFormat
{
NumberFormatId = 0U,
FontId = 1U,
FillId = 4U,
BorderId = 1U,
FormatId = 0U,
ApplyFill = true
};
cellFormats.Append(generalFormat);
cellFormats.Append(headerFormat);
cellFormats.Append(rowFormat);
cellFormats.Append(alternateFormat);
#endregion
#region CellStyles
var cellStyles = new CellStyles
{
Count = 1U
};
var cellStyle = new CellStyle
{
Name = "Normal",
FormatId = 0U,
BuiltinId = 0U
};
cellStyles.Append(cellStyle);
#endregion
#endregion
stylesheet.Append(fonts);
stylesheet.Append(fills);
stylesheet.Append(borders);
stylesheet.Append(cellStyleFormats);
stylesheet.Append(cellFormats);
stylesheet.Append(cellStyles);
return stylesheet;
}
#endregion
static void SetColumnWidth(Worksheet worksheet, uint Index, DoubleValue dwidth)
{
DocumentFormat.OpenXml.Spreadsheet.Columns cs = worksheet.GetFirstChild();
cs = new DocumentFormat.OpenXml.Spreadsheet.Columns();
DocumentFormat.OpenXml.Spreadsheet.Column c = new DocumentFormat.OpenXml.Spreadsheet.Column() { Min = Index, Max = Index, Width = dwidth, CustomWidth = true };
cs.Append(c);
worksheet.InsertAfter(cs, worksheet.GetFirstChild());
}
}
} | |