/*******************************************************************************
* You may amend and distribute as you like, but don't remove this header!
*
* EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
* See http://www.codeplex.com/EPPlus for details.
*
* Copyright (C) 2011 Jan Källman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
* If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
*
* All code and executables are provided "as is" with no warranty either express or implied.
* The author accepts no liability for any damage or loss of business that this product may cause.
*
* Code change notes:
*
* Author Change Date
* ******************************************************************************
* Jan Källman Initial Release 2009-10-01
* Jan Källman License changed GPL-->LGPL 2011-12-27
*******************************************************************************/
using System;
using System.Xml;
using System.Collections.Generic;
using draw=System.Drawing;
using OfficeOpenXml.Style;
using OfficeOpenXml.Style.XmlAccess;
using OfficeOpenXml.Style.Dxf;
using OfficeOpenXml.ConditionalFormatting;
namespace OfficeOpenXml
{
///
/// Containts all shared cell styles for a workbook
///
public sealed class ExcelStyles : XmlHelper
{
const string NumberFormatsPath = "d:styleSheet/d:numFmts";
const string FontsPath = "d:styleSheet/d:fonts";
const string FillsPath = "d:styleSheet/d:fills";
const string BordersPath = "d:styleSheet/d:borders";
const string CellStyleXfsPath = "d:styleSheet/d:cellStyleXfs";
const string CellXfsPath = "d:styleSheet/d:cellXfs";
const string CellStylesPath = "d:styleSheet/d:cellStyles";
const string dxfsPath = "d:styleSheet/d:dxfs";
//internal Dictionary Styles = new Dictionary();
XmlDocument _styleXml;
ExcelWorkbook _wb;
XmlNamespaceManager _nameSpaceManager;
internal int _nextDfxNumFmtID = 164;
internal ExcelStyles(XmlNamespaceManager NameSpaceManager, XmlDocument xml, ExcelWorkbook wb) :
base(NameSpaceManager, xml)
{
_styleXml=xml;
_wb = wb;
_nameSpaceManager = NameSpaceManager;
SchemaNodeOrder = new string[] { "numFmts", "fonts", "fills", "borders", "cellStyleXfs", "cellXfs", "cellStyles", "dxfs" };
LoadFromDocument();
}
///
/// Loads the style XML to memory
///
private void LoadFromDocument()
{
//NumberFormats
ExcelNumberFormatXml.AddBuildIn(NameSpaceManager, NumberFormats);
XmlNode numNode = _styleXml.SelectSingleNode(NumberFormatsPath, _nameSpaceManager);
if (numNode != null)
{
foreach (XmlNode n in numNode)
{
ExcelNumberFormatXml nf = new ExcelNumberFormatXml(_nameSpaceManager, n);
NumberFormats.Add(nf.Id, nf);
if (nf.NumFmtId >= NumberFormats.NextId) NumberFormats.NextId=nf.NumFmtId+1;
}
}
//Fonts
XmlNode fontNode = _styleXml.SelectSingleNode(FontsPath, _nameSpaceManager);
foreach (XmlNode n in fontNode)
{
ExcelFontXml f = new ExcelFontXml(_nameSpaceManager, n);
Fonts.Add(f.Id, f);
}
//Fills
XmlNode fillNode = _styleXml.SelectSingleNode(FillsPath, _nameSpaceManager);
foreach (XmlNode n in fillNode)
{
ExcelFillXml f;
if (n.FirstChild != null && n.FirstChild.LocalName == "gradientFill")
{
f = new ExcelGradientFillXml(_nameSpaceManager, n);
}
else
{
f = new ExcelFillXml(_nameSpaceManager, n);
}
Fills.Add(f.Id, f);
}
//Borders
XmlNode borderNode = _styleXml.SelectSingleNode(BordersPath, _nameSpaceManager);
foreach (XmlNode n in borderNode)
{
ExcelBorderXml b = new ExcelBorderXml(_nameSpaceManager, n);
Borders.Add(b.Id, b);
}
//cellStyleXfs
XmlNode styleXfsNode = _styleXml.SelectSingleNode(CellStyleXfsPath, _nameSpaceManager);
if (styleXfsNode != null)
{
foreach (XmlNode n in styleXfsNode)
{
ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
CellStyleXfs.Add(item.Id, item);
}
}
XmlNode styleNode = _styleXml.SelectSingleNode(CellXfsPath, _nameSpaceManager);
for (int i = 0; i < styleNode.ChildNodes.Count; i++)
{
XmlNode n = styleNode.ChildNodes[i];
ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
CellXfs.Add(item.Id, item);
}
//cellStyle
XmlNode namedStyleNode = _styleXml.SelectSingleNode(CellStylesPath, _nameSpaceManager);
if (namedStyleNode != null)
{
foreach (XmlNode n in namedStyleNode)
{
ExcelNamedStyleXml item = new ExcelNamedStyleXml(_nameSpaceManager, n, this);
NamedStyles.Add(item.Name, item);
}
}
//dxfsPath
XmlNode dxfsNode = _styleXml.SelectSingleNode(dxfsPath, _nameSpaceManager);
if (dxfsNode != null)
{
foreach (XmlNode x in dxfsNode)
{
ExcelDxfStyleConditionalFormatting item = new ExcelDxfStyleConditionalFormatting(_nameSpaceManager, x, this);
Dxfs.Add(item.Id, item);
}
}
}
internal ExcelStyle GetStyleObject(int Id,int PositionID, string Address)
{
if (Id < 0) Id = 0;
return new ExcelStyle(this, PropertyChange, PositionID, Address, Id);
}
///
/// Handels changes of properties on the style objects
///
///
///
///
internal int PropertyChange(StyleBase sender, Style.StyleChangeEventArgs e)
{
var address = new ExcelAddressBase(e.Address);
var ws = _wb.Worksheets[e.PositionID];
Dictionary styleCashe = new Dictionary();
//Set single address
SetStyleAddress(sender, e, address, ws, ref styleCashe);
if (address.Addresses != null)
{
//Handle multiaddresses
foreach (var innerAddress in address.Addresses)
{
SetStyleAddress(sender, e, innerAddress, ws, ref styleCashe);
}
}
return 0;
}
private void SetStyleAddress(StyleBase sender, Style.StyleChangeEventArgs e, ExcelAddressBase address, ExcelWorksheet ws, ref Dictionary styleCashe)
{
if (address.Start.Column == 0 || address.Start.Row == 0)
{
throw (new Exception("error address"));
}
//Columns
else if (address.Start.Row == 1 && address.End.Row == ExcelPackage.MaxRows)
{
ExcelColumn column;
//Get the startcolumn
ulong colID = ExcelColumn.GetColumnID(ws.SheetID, address.Start.Column);
if (!ws._columns.ContainsKey(colID))
{
column=ws.Column(address.Start.Column);
}
else
{
column = ws._columns[colID] as ExcelColumn;
}
var index = ws._columns.IndexOf(colID);
while(column.ColumnMin <= address.End.Column)
{
if (column.ColumnMax > address.End.Column)
{
var newCol = ws.CopyColumn(column, address.End.Column + 1, column.ColumnMax);
column.ColumnMax = address.End.Column;
}
if (styleCashe.ContainsKey(column.StyleID))
{
column.StyleID = styleCashe[column.StyleID];
}
else
{
ExcelXfs st = CellXfs[column.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(column.StyleID, newId);
column.StyleID = newId;
}
index++;
if (index >= ws._columns.Count)
{
break;
}
else
{
column = (ws._columns[index] as ExcelColumn);
}
}
if (column._columnMax < address.End.Column)
{
var newCol = ws.Column(column._columnMax + 1) as ExcelColumn;
newCol._columnMax = address.End.Column;
if (styleCashe.ContainsKey(newCol.StyleID))
{
newCol.StyleID = styleCashe[newCol.StyleID];
}
else
{
ExcelXfs st = CellXfs[column.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(newCol.StyleID, newId);
newCol.StyleID = newId;
}
//column._columnMax = address.End.Column;
}
//Set for individual cells in the spann. We loop all cells here since the cells are sorted with columns first.
foreach (ExcelCell cell in ws._cells)
{
if (cell.Column >= address.Start.Column &&
cell.Column <= address.End.Column)
{
if (styleCashe.ContainsKey(cell.StyleID))
{
cell.StyleID = styleCashe[cell.StyleID];
}
else
{
ExcelXfs st = CellXfs[cell.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(cell.StyleID, newId);
cell.StyleID = newId;
}
}
}
}
//Rows
else if(address.Start.Column==1 && address.End.Column==ExcelPackage.MaxColumns)
{
for (int rowNum = address.Start.Row; rowNum <= address.End.Row; rowNum++)
{
ExcelRow row = ws.Row(rowNum);
if (row.StyleID == 0 && ws._columns.Count > 0)
{
//TODO: We should loop all columns here and change each cell. But for now we take style of column A.
foreach (ExcelColumn column in ws._columns)
{
row.StyleID = column.StyleID;
break; //Get the first one and break.
}
}
if (styleCashe.ContainsKey(row.StyleID))
{
row.StyleID = styleCashe[row.StyleID];
}
else
{
ExcelXfs st = CellXfs[row.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(row.StyleID, newId);
row.StyleID = newId;
}
}
//Get Start Cell
ulong rowID = ExcelRow.GetRowID(ws.SheetID, address.Start.Row);
int index = ws._cells.IndexOf(rowID);
index = ~index;
while (index < ws._cells.Count)
{
var cell = ws._cells[index] as ExcelCell;
if(cell.Row > address.End.Row)
{
break;
}
if (styleCashe.ContainsKey(cell.StyleID))
{
cell.StyleID = styleCashe[cell.StyleID];
}
else
{
ExcelXfs st = CellXfs[cell.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(cell.StyleID, newId);
cell.StyleID = newId;
}
index++;
}
}
else //Cellrange
{
for (int col = address.Start.Column; col <= address.End.Column; col++)
{
for (int row = address.Start.Row; row <= address.End.Row; row++)
{
ExcelCell cell = ws.Cell(row, col);
if (styleCashe.ContainsKey(cell.StyleID))
{
cell.StyleID = styleCashe[cell.StyleID];
}
else
{
ExcelXfs st = CellXfs[cell.StyleID];
int newId = st.GetNewID(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
styleCashe.Add(cell.StyleID, newId);
cell.StyleID = newId;
}
}
}
}
}
///
/// Handles property changes on Named styles.
///
///
///
///
internal int NamedStylePropertyChange(StyleBase sender, Style.StyleChangeEventArgs e)
{
int index = NamedStyles.FindIndexByID(e.Address);
if (index >= 0)
{
int newId = CellStyleXfs[NamedStyles[index].StyleXfId].GetNewID(CellStyleXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
int prevIx=NamedStyles[index].StyleXfId;
NamedStyles[index].StyleXfId = newId;
NamedStyles[index].Style.Index = newId;
NamedStyles[index].XfId = int.MinValue;
foreach (var style in CellXfs)
{
if (style.XfId == prevIx)
{
style.XfId = newId;
}
}
}
return 0;
}
public ExcelStyleCollection NumberFormats = new ExcelStyleCollection();
public ExcelStyleCollection Fonts = new ExcelStyleCollection();
public ExcelStyleCollection Fills = new ExcelStyleCollection();
public ExcelStyleCollection Borders = new ExcelStyleCollection();
public ExcelStyleCollection CellStyleXfs = new ExcelStyleCollection();
public ExcelStyleCollection CellXfs = new ExcelStyleCollection();
public ExcelStyleCollection NamedStyles = new ExcelStyleCollection();
public ExcelStyleCollection Dxfs = new ExcelStyleCollection();
internal string Id
{
get { return ""; }
}
public ExcelNamedStyleXml CreateNamedStyle(string name)
{
return CreateNamedStyle(name, null);
}
public ExcelNamedStyleXml CreateNamedStyle(string name, ExcelStyle Template)
{
if (_wb.Styles.NamedStyles.ExistsKey(name))
{
throw new Exception(string.Format("Key {0} already exists in collection", name));
}
ExcelNamedStyleXml style;
style = new ExcelNamedStyleXml(NameSpaceManager, this);
int xfIdCopy, positionID;
ExcelStyles styles;
if (Template == null)
{
// style.Style = new ExcelStyle(this, NamedStylePropertyChange, -1, name, 0);
xfIdCopy = 0;
positionID = -1;
styles = this;
}
else
{
if (Template.PositionID < 0 && Template.Styles==this)
{
xfIdCopy = Template.Index;
positionID=Template.PositionID;
styles = this;
//style.Style = new ExcelStyle(this, NamedStylePropertyChange, Template.PositionID, name, Template.Index);
//style.StyleXfId = Template.Index;
}
else
{
xfIdCopy = Template.XfId;
positionID = -1;
styles = Template.Styles;
}
}
//Clone namedstyle
int styleXfId = CloneStyle(styles, xfIdCopy, true);
//Close cells style
CellStyleXfs[styleXfId].XfId = CellStyleXfs.Count-1;
int xfid = CloneStyle(styles, xfIdCopy, false, true); //Always add a new style (We create a new named style here)
CellXfs[xfid].XfId = styleXfId;
style.Style = new ExcelStyle(this, NamedStylePropertyChange, positionID, name, styleXfId);
style.StyleXfId = styleXfId;
style.Name = name;
int ix =_wb.Styles.NamedStyles.Add(style.Name, style);
style.Style.SetIndex(ix);
//style.Style.XfId = ix;
return style;
}
public void UpdateXml()
{
RemoveUnusedStyles();
//NumberFormat
XmlNode nfNode=_styleXml.SelectSingleNode(NumberFormatsPath, _nameSpaceManager);
if (nfNode == null)
{
CreateNode(NumberFormatsPath, true);
nfNode = _styleXml.SelectSingleNode(NumberFormatsPath, _nameSpaceManager);
}
else
{
nfNode.RemoveAll();
}
int count = 0;
int normalIx = NamedStyles.FindIndexByID("Normal");
if (NamedStyles.Count > 0 && normalIx>=0 && NamedStyles[normalIx].Style.Numberformat.NumFmtID >= 164)
{
ExcelNumberFormatXml nf = NumberFormats[NumberFormats.FindIndexByID(NamedStyles[normalIx].Style.Numberformat.Id)];
nfNode.AppendChild(nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage.schemaMain)));
nf.newID = count++;
}
foreach (ExcelNumberFormatXml nf in NumberFormats)
{
if(!nf.BuildIn /*&& nf.newID<0*/) //Buildin formats are not updated.
{
nfNode.AppendChild(nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage.schemaMain)));
nf.newID = count;
count++;
}
}
(nfNode as XmlElement).SetAttribute("count", count.ToString());
//Font
count=0;
XmlNode fntNode = _styleXml.SelectSingleNode(FontsPath, _nameSpaceManager);
fntNode.RemoveAll();
//Normal should be first in the collection
if (NamedStyles.Count > 0 && normalIx >= 0 && NamedStyles[normalIx].Style.Font.Index > 0)
{
ExcelFontXml fnt = Fonts[NamedStyles[normalIx].Style.Font.Index];
fntNode.AppendChild(fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage.schemaMain)));
fnt.newID = count++;
}
foreach (ExcelFontXml fnt in Fonts)
{
if (fnt.useCnt > 0/* && fnt.newID<0*/)
{
fntNode.AppendChild(fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage.schemaMain)));
fnt.newID = count;
count++;
}
}
(fntNode as XmlElement).SetAttribute("count", count.ToString());
//Fills
count = 0;
XmlNode fillsNode = _styleXml.SelectSingleNode(FillsPath, _nameSpaceManager);
fillsNode.RemoveAll();
Fills[0].useCnt = 1; //Must exist (none);
Fills[1].useCnt = 1; //Must exist (gray125);
foreach (ExcelFillXml fill in Fills)
{
if (fill.useCnt > 0)
{
fillsNode.AppendChild(fill.CreateXmlNode(_styleXml.CreateElement("fill", ExcelPackage.schemaMain)));
fill.newID = count;
count++;
}
}
(fillsNode as XmlElement).SetAttribute("count", count.ToString());
//Borders
count = 0;
XmlNode bordersNode = _styleXml.SelectSingleNode(BordersPath, _nameSpaceManager);
bordersNode.RemoveAll();
Borders[0].useCnt = 1; //Must exist blank;
foreach (ExcelBorderXml border in Borders)
{
if (border.useCnt > 0)
{
bordersNode.AppendChild(border.CreateXmlNode(_styleXml.CreateElement("border", ExcelPackage.schemaMain)));
border.newID = count;
count++;
}
}
(bordersNode as XmlElement).SetAttribute("count", count.ToString());
XmlNode styleXfsNode = _styleXml.SelectSingleNode(CellStyleXfsPath, _nameSpaceManager);
if (styleXfsNode == null && NamedStyles.Count > 0)
{
CreateNode(CellStyleXfsPath);
styleXfsNode = _styleXml.SelectSingleNode(CellStyleXfsPath, _nameSpaceManager);
}
if (NamedStyles.Count > 0)
{
styleXfsNode.RemoveAll();
}
//NamedStyles
count = normalIx > -1 ? 1 : 0; //If we have a normal style, we make sure it's added first.
XmlNode cellStyleNode = _styleXml.SelectSingleNode(CellStylesPath, _nameSpaceManager);
if(cellStyleNode!=null)
{
cellStyleNode.RemoveAll();
}
XmlNode cellXfsNode = _styleXml.SelectSingleNode(CellXfsPath, _nameSpaceManager);
cellXfsNode.RemoveAll();
if (NamedStyles.Count > 0 && normalIx >= 0)
{
NamedStyles[normalIx].newID = 0;
AddNamedStyle(0, styleXfsNode, cellXfsNode, NamedStyles[normalIx]);
}
foreach (ExcelNamedStyleXml style in NamedStyles)
{
if (style.Name.ToLower() != "normal")
{
style.newID = count;
AddNamedStyle(count++, styleXfsNode, cellXfsNode, style);
}
else
{
style.newID = 0;
}
cellStyleNode.AppendChild(style.CreateXmlNode(_styleXml.CreateElement("cellStyle", ExcelPackage.schemaMain)));
}
if (cellStyleNode!=null) (cellStyleNode as XmlElement).SetAttribute("count", count.ToString());
if (styleXfsNode != null) (styleXfsNode as XmlElement).SetAttribute("count", count.ToString());
//CellStyle
int xfix = 0;
foreach (ExcelXfs xf in CellXfs)
{
if (xf.useCnt > 0 && !(normalIx == xfix))
{
cellXfsNode.AppendChild(xf.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage.schemaMain)));
xf.newID = count;
count++;
}
xfix++;
}
(cellXfsNode as XmlElement).SetAttribute("count", count.ToString());
//Set dxf styling for conditional Formatting
XmlNode dxfsNode = _styleXml.SelectSingleNode(dxfsPath, _nameSpaceManager);
foreach (var ws in _wb.Worksheets)
{
foreach (var cf in ws.ConditionalFormatting)
{
if (cf.Style.HasValue)
{
int ix = Dxfs.FindIndexByID(cf.Style.Id);
if (ix < 0)
{
((ExcelConditionalFormattingRule)cf).DxfId = Dxfs.Count;
Dxfs.Add(cf.Style.Id, cf.Style);
var elem = ((XmlDocument)TopNode).CreateElement("d", "dxf", ExcelPackage.schemaMain);
cf.Style.CreateNodes(new XmlHelperInstance(NameSpaceManager, elem), "");
dxfsNode.AppendChild(elem);
}
else
{
((ExcelConditionalFormattingRule)cf).DxfId = ix;
}
}
}
}
}
private void AddNamedStyle(int id, XmlNode styleXfsNode,XmlNode cellXfsNode, ExcelNamedStyleXml style)
{
var styleXfs = CellStyleXfs[style.StyleXfId];
styleXfsNode.AppendChild(styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage.schemaMain), true));
styleXfs.newID = id;
styleXfs.XfId = style.StyleXfId;
var ix = CellXfs.FindIndexByID(styleXfs.Id);
if (ix < 0)
{
cellXfsNode.AppendChild(styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage.schemaMain)));
}
else
{
if (id < 0) CellXfs[ix].XfId = id;
cellXfsNode.AppendChild(CellXfs[ix].CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage.schemaMain)));
CellXfs[ix].useCnt = 0;
CellXfs[ix].newID = id;
}
if (style.XfId >= 0)
style.XfId = CellXfs[style.XfId].newID;
else
style.XfId = 0;
}
private void RemoveUnusedStyles()
{
CellXfs[0].useCnt = 1; //First item is allways used.
foreach (ExcelWorksheet sheet in _wb.Worksheets)
{
foreach (ExcelCell cell in sheet._cells) //sheet._cells.Values
{
CellXfs[cell.GetCellStyleID()].useCnt++;
}
foreach(ExcelRow row in sheet._rows)
{
CellXfs[row.StyleID].useCnt++;
}
foreach (ExcelColumn col in sheet._columns)
{
if(col.StyleID>=0) CellXfs[col.StyleID].useCnt++;
}
}
foreach (ExcelNamedStyleXml ns in NamedStyles)
{
CellStyleXfs[ns.StyleXfId].useCnt++;
}
foreach (ExcelXfs xf in CellXfs)
{
if (xf.useCnt > 0)
{
if (xf.FontId >= 0) Fonts[xf.FontId].useCnt++;
if (xf.FillId >= 0) Fills[xf.FillId].useCnt++;
if (xf.BorderId >= 0) Borders[xf.BorderId].useCnt++;
}
}
foreach (ExcelXfs xf in CellStyleXfs)
{
if (xf.useCnt > 0)
{
if (xf.FontId >= 0) Fonts[xf.FontId].useCnt++;
if (xf.FillId >= 0) Fills[xf.FillId].useCnt++;
if (xf.BorderId >= 0) Borders[xf.BorderId].useCnt++;
}
}
}
internal int GetStyleIdFromName(string Name)
{
int i = NamedStyles.FindIndexByID(Name);
if (i >= 0)
{
int id = NamedStyles[i].XfId;
if (id < 0)
{
int styleXfId=NamedStyles[i].StyleXfId;
ExcelXfs newStyle = CellStyleXfs[styleXfId].Copy();
newStyle.XfId = styleXfId;
id = CellXfs.FindIndexByID(newStyle.Id);
if (id < 0)
{
id = CellXfs.Add(newStyle.Id, newStyle);
}
NamedStyles[i].XfId=id;
}
return id;
}
else
{
return 0;
//throw(new Exception("Named style does not exist"));
}
}
#region XmlHelpFunctions
private int GetXmlNodeInt(XmlNode node)
{
int i;
if (int.TryParse(GetXmlNode(node), out i))
{
return i;
}
else
{
return 0;
}
}
private string GetXmlNode(XmlNode node)
{
if (node == null)
{
return "";
}
if (node.Value != null)
{
return node.Value;
}
else
{
return "";
}
}
#endregion
internal int CloneStyle(ExcelStyles style, int styleID)
{
return CloneStyle(style, styleID, false, false);
}
internal int CloneStyle(ExcelStyles style, int styleID, bool isNamedStyle)
{
return CloneStyle(style, styleID, isNamedStyle, false);
}
internal int CloneStyle(ExcelStyles style, int styleID, bool isNamedStyle, bool allwaysAdd)
{
ExcelXfs xfs;
if (isNamedStyle)
{
xfs = style.CellStyleXfs[styleID];
}
else
{
xfs = style.CellXfs[styleID];
}
ExcelXfs newXfs=xfs.Copy(this);
//Numberformat
if (xfs.NumberFormatId > 0)
{
string format="";
foreach (var fmt in style.NumberFormats)
{
if (fmt.NumFmtId == xfs.NumberFormatId)
{
format=fmt.Format;
break;
}
}
int ix=NumberFormats.FindIndexByID(format);
if (ix<0)
{
ExcelNumberFormatXml item = new ExcelNumberFormatXml(NameSpaceManager) { Format = format, NumFmtId = NumberFormats.NextId++ };
NumberFormats.Add(format, item);
ix=item.NumFmtId;
}
newXfs.NumberFormatId= ix;
}
//Font
if (xfs.FontId > -1)
{
int ix=Fonts.FindIndexByID(xfs.Font.Id);
if (ix<0)
{
ExcelFontXml item = style.Fonts[xfs.FontId].Copy();
ix=Fonts.Add(xfs.Font.Id, item);
}
newXfs.FontId=ix;
}
//Border
if (xfs.BorderId > -1)
{
int ix = Borders.FindIndexByID(xfs.Border.Id);
if (ix < 0)
{
ExcelBorderXml item = style.Borders[xfs.BorderId].Copy();
ix = Borders.Add(xfs.Border.Id, item);
}
newXfs.BorderId = ix;
}
//Fill
if (xfs.FillId > -1)
{
int ix = Fills.FindIndexByID(xfs.Fill.Id);
if (ix < 0)
{
var item = style.Fills[xfs.FillId].Copy();
ix = Fills.Add(xfs.Fill.Id, item);
}
newXfs.FillId = ix;
}
//Named style reference
if (xfs.XfId > 0)
{
var id = style.CellStyleXfs[xfs.XfId].Id;
var newId = CellStyleXfs.FindIndexByID(id);
//if (newId < 0)
//{
// newXfs.XfId = CloneStyle(style, xfs.XfId, true);
//}
//else
//{
newXfs.XfId = newId;
//}
}
int index;
if (isNamedStyle)
{
index = CellStyleXfs.Add(newXfs.Id, newXfs);
}
else
{
if (allwaysAdd)
{
index = CellXfs.Add(newXfs.Id, newXfs);
}
else
{
index = CellXfs.FindIndexByID(newXfs.Id);
if (index < 0)
{
index = CellXfs.Add(newXfs.Id, newXfs);
}
}
}
return index;
}
}
}