1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185 |
- // Copyright (c) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
- using System;
- using System.Text;
- using System.Collections.Generic;
- using System.Linq;
- using System.Xml.Linq;
- using DocumentFormat.OpenXml.Packaging;
- using System.Xml;
- using ExcelFormula;
- namespace OpenXmlPowerTools
- {
- // Classes for "bulk load" of a spreadsheet
- public class MemorySpreadsheet
- {
- private SortedList<int, MemoryRow> rowList;
- public MemorySpreadsheet()
- {
- rowList = new SortedList<int, MemoryRow>();
- }
- public void SetCellValue(int row, int column, object value)
- {
- if (!rowList.ContainsKey(row))
- rowList.Add(row, new MemoryRow(row));
- MemoryRow mr = rowList[row];
- mr.SetCell(new MemoryCell(column, value));
- }
- public void SetCellValue(int row, int column, object value, int styleIndex)
- {
- if (!rowList.ContainsKey(row))
- rowList.Add(row, new MemoryRow(row));
- MemoryRow mr = rowList[row];
- mr.SetCell(new MemoryCell(column, value, styleIndex));
- }
- public object GetCellValue(int row, int column)
- {
- if (!rowList.ContainsKey(row))
- return null;
- MemoryCell cell = rowList[row].GetCell(column);
- if (cell == null)
- return null;
- return cell.GetValue();
- }
- public XElement GetElements()
- {
- XElement root = new XElement(S.sheetData);
- foreach (KeyValuePair<int, MemoryRow> item in rowList)
- root.Add(item.Value.GetElements());
- return root;
- }
- }
- public class MemoryRow
- {
- private int row;
- private SortedList<int, MemoryCell> cellList;
- public MemoryRow(int Row)
- {
- row = Row;
- cellList = new SortedList<int, MemoryCell>();
- }
- public MemoryCell GetCell(int column)
- {
- if (!cellList.ContainsKey(column))
- return null;
- return cellList[column];
- }
- public void SetCell(MemoryCell cell)
- {
- if (cellList.ContainsKey(cell.GetColumn()))
- cellList.Remove(cell.GetColumn());
- cellList.Add(cell.GetColumn(), cell);
- }
- public XElement GetElements()
- {
- XElement root = new XElement(S.row, new XAttribute(NoNamespace.r, row));
- foreach (KeyValuePair<int, MemoryCell> item in cellList)
- root.Add(item.Value.GetElements(row));
- return root;
- }
- }
- public class MemoryCell
- {
- private int column;
- private object cellValue;
- private int styleIndex;
- public MemoryCell(int col, object value)
- {
- column = col;
- cellValue = value;
- }
- public MemoryCell(int col, object value, int style)
- {
- column = col;
- cellValue = value;
- styleIndex = style;
- }
- public int GetColumn()
- {
- return column;
- }
- public object GetValue()
- {
- return cellValue;
- }
- public int GetStyleIndex()
- {
- return styleIndex;
- }
- public XElement GetElements(int row)
- {
- string cellReference = WorksheetAccessor.GetColumnId(column) + row.ToString();
- XElement newCell = null;
- if (cellValue is int || cellValue is double)
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XElement(S.v, cellValue.ToString()));
- else if (cellValue is bool)
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "b"), new XElement(S.v, (bool)cellValue ? "1" : "0"));
- else if (cellValue is string)
- {
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "inlineStr"),
- new XElement(S._is, new XElement(S.t, cellValue.ToString())));
- }
- if (newCell == null)
- throw new ArgumentException("Invalid cell type.");
- if (styleIndex != 0)
- newCell.Add(new XAttribute(NoNamespace.s, styleIndex));
- return newCell;
- }
- }
- // Static methods to modify worksheets in SpreadsheetML
- public class WorksheetAccessor
- {
- private static XNamespace ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
- private static XNamespace relationshipsns = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
- // Finds the WorksheetPart by sheet name
- public static WorksheetPart GetWorksheet(SpreadsheetDocument document, string worksheetName)
- {
- XDocument workbook = document.WorkbookPart.GetXDocument();
- return (WorksheetPart)document.WorkbookPart.GetPartById(
- workbook.Root.Element(S.sheets).Elements(S.sheet).Where(
- s => s.Attribute(NoNamespace.name).Value.ToLower().Equals(worksheetName.ToLower()))
- .FirstOrDefault().Attribute(R.id).Value);
- }
- // Creates a new worksheet with the specified name
- public static WorksheetPart AddWorksheet(SpreadsheetDocument document, string worksheetName)
- {
- // Create the empty sheet
- WorksheetPart worksheetPart = document.WorkbookPart.AddNewPart<WorksheetPart>();
- worksheetPart.PutXDocument(new XDocument(
- new XElement(S.worksheet, new XAttribute("xmlns", S.s), new XAttribute(XNamespace.Xmlns + "r", R.r),
- new XElement(S.sheetData))));
- XDocument wb = document.WorkbookPart.GetXDocument();
- // Generate a unique sheet ID number
- int sheetId = 1;
- if (wb.Root.Element(S.sheets).Elements(S.sheet).Count() != 0)
- sheetId = wb.Root.Element(S.sheets).Elements(S.sheet).Max(n => Convert.ToInt32(n.Attribute(NoNamespace.sheetId).Value)) + 1;
- // If name is null, generate a name based on the sheet ID
- if (worksheetName == null)
- worksheetName = "Sheet" + sheetId.ToString();
- // Create the new sheet element in the workbook
- wb.Root.Element(S.sheets).Add(new XElement(S.sheet,
- new XAttribute(NoNamespace.name, worksheetName),
- new XAttribute(NoNamespace.sheetId, sheetId),
- new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(worksheetPart))));
- document.WorkbookPart.PutXDocument();
- return worksheetPart;
- }
- // Creates a new worksheet with the specified name and contents from a memory spreadsheet
- public static void SetSheetContents(SpreadsheetDocument document, WorksheetPart worksheet, MemorySpreadsheet contents)
- {
- XDocument worksheetXDocument = worksheet.GetXDocument();
- worksheetXDocument.Root.Element(S.sheetData).ReplaceWith(contents.GetElements());
- worksheet.PutXDocument();
- }
- // Translates the column number to the column reference string (e.g. 1 -> A, 2-> B)
- public static string GetColumnId(int columnNumber)
- {
- string result = "";
- do
- {
- result = ((char)((columnNumber - 1) % 26 + (int)'A')).ToString() + result;
- columnNumber = (columnNumber - 1) / 26;
- } while (columnNumber != 0);
- return result;
- }
- // Gets the value of the specified cell
- // Returned object can be double/Double, int/Int32, bool/Boolean or string/String types
- public static object GetCellValue(SpreadsheetDocument document, WorksheetPart worksheet, int column, int row)
- {
- XDocument worksheetXDocument = worksheet.GetXDocument();
- XElement cellValue = GetCell(worksheetXDocument, column, row);
- if (cellValue != null)
- {
- if (cellValue.Attribute(NoNamespace.t) == null)
- {
- string value = cellValue.Element(S.v).Value;
- if (value.Contains("."))
- return Convert.ToDouble(value);
- return Convert.ToInt32(value);
- }
- switch (cellValue.Attribute(NoNamespace.t).Value)
- {
- case "b":
- return (cellValue.Element(S.v).Value == "1");
- case "s":
- return GetSharedString(document, System.Convert.ToInt32(cellValue.Element(S.v).Value));
- case "inlineStr":
- return cellValue.Element(S._is).Element(S.t).Value;
- }
- }
- return null;
- }
- // Finds the shared string using its index
- private static string GetSharedString(SpreadsheetDocument document, int index)
- {
- XDocument sharedStringsXDocument = document.WorkbookPart.SharedStringTablePart.GetXDocument();
- return sharedStringsXDocument.Root.Elements().ElementAt<XElement>(index).Value;
- }
- // Gets the cell element (c) for the specified cell
- private static XElement GetCell(XDocument worksheet, int column, int row)
- {
- string cellReference = GetColumnId(column) + row.ToString();
- XElement rowElement = worksheet.Root
- .Element(S.sheetData)
- .Elements(S.row)
- .Where(r => r.Attribute(NoNamespace.r).Value.Equals(row.ToString())).FirstOrDefault<XElement>();
- if (rowElement == null)
- return null;
- return rowElement.Elements(S.c).Where(c => c.Attribute(NoNamespace.r).Value.Equals(cellReference)).FirstOrDefault<XElement>();
- }
- // Sets the value for the specified cell
- // The "value" must be double/Double, int/Int32, bool/Boolean or string/String type
- public static void SetCellValue(SpreadsheetDocument document, WorksheetPart worksheet, int row, int column, object value)
- {
- XDocument worksheetXDocument = worksheet.GetXDocument();
- string cellReference = GetColumnId(column) + row.ToString();
- XElement newCell = null;
- if (value is int || value is double)
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XElement(S.v, value.ToString()));
- else if (value is bool)
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "b"), new XElement(S.v, (bool)value ? "1" : "0"));
- else if (value is string)
- {
- newCell = new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "inlineStr"),
- new XElement(S._is, new XElement(S.t, value.ToString())));
- }
- if (newCell == null)
- throw new ArgumentException("Invalid cell type.");
- SetCell(worksheetXDocument, newCell);
- }
- // Sets the specified cell
- private static void SetCell(XDocument worksheetXDocument, XElement newCell)
- {
- int row;
- int column;
- string cellReference = newCell.Attribute(NoNamespace.r).Value;
- GetRowColumn(cellReference, out row, out column);
- // Find the row containing the cell to add the value to
- XElement rowElement = worksheetXDocument.Root
- .Element(S.sheetData)
- .Elements(S.row)
- .Where(t => t.Attribute(NoNamespace.r).Value == row.ToString())
- .FirstOrDefault();
- if (rowElement == null)
- {
- //row element does not exist
- //create a new one
- rowElement = CreateEmptyRow(row);
- //row elements must appear in order inside sheetData element
- if (worksheetXDocument.Root.Element(S.sheetData).HasElements)
- { //if there are more rows already defined at sheetData element
- //find the row with the inmediate higher index for the row containing the cell to set the value to
- XElement rowAfterElement = FindRowAfter(worksheetXDocument, row);
- //if there is a row with an inmediate higher index already defined at sheetData
- if (rowAfterElement != null)
- {
- //add the new row before the row with an inmediate higher index
- rowAfterElement.AddBeforeSelf(rowElement);
- }
- else
- { //this row is going to be the one with the highest index (add it as the last element for sheetData)
- worksheetXDocument.Root.Element(S.sheetData).Elements(S.row).Last().AddAfterSelf(rowElement);
- }
- }
- else
- { //there are no other rows already defined at sheetData
- //Add a new row elemento to sheetData
- worksheetXDocument.Root.Element(S.sheetData).Add(rowElement);
- }
- //Add the new cell to the row Element
- rowElement.Add(newCell);
- }
- else
- {
- //row containing the cell to set the value to is already defined at sheetData
- //look if cell already exist at that row
- XElement currentCell = rowElement
- .Elements(S.c)
- .Where(t => t.Attribute(NoNamespace.r).Value == cellReference)
- .FirstOrDefault();
- if (currentCell == null)
- { //cell element does not exist at row indicated as parameter
- //find the inmediate right column for the cell to set the value to
- XElement columnAfterXElement = FindColumAfter(worksheetXDocument, row, column);
- if (columnAfterXElement != null)
- {
- //Insert the new cell before the inmediate right column
- columnAfterXElement.AddBeforeSelf(newCell);
- }
- else
- { //There is no inmediate right cell
- //Add the new cell as the last element for the row
- rowElement.Add(newCell);
- }
- }
- else
- {
- //cell alreay exist
- //replace the current cell with that with the new value
- currentCell.ReplaceWith(newCell);
- }
- }
- }
- // Finds the row element (r) with a higher number than the specified "row" number
- private static XElement FindRowAfter(XDocument worksheet, int row)
- {
- return worksheet.Root
- .Element(S.sheetData)
- .Elements(S.row)
- .FirstOrDefault(r => System.Convert.ToInt32(r.Attribute(NoNamespace.r).Value) > row);
- }
- // Finds the cell element (c) in the specified row that is after the specified "column" number
- private static XElement FindColumAfter(XDocument worksheet, int row, int column)
- {
- return worksheet.Root
- .Element(S.sheetData)
- .Elements(S.row)
- .FirstOrDefault(r => System.Convert.ToInt32(r.Attribute(NoNamespace.r).Value) == row)
- .Elements(S.c)
- .FirstOrDefault(c => GetColumnNumber(c.Attribute(NoNamespace.r).Value) > GetColumnNumber(GetColumnId(column) + row));
- }
- // Converts the column reference string to a column number (e.g. A -> 1, B -> 2)
- public static int GetColumnNumber(string cellReference)
- {
- int columnNumber = 0;
- foreach (char c in cellReference)
- {
- if (Char.IsLetter(c))
- columnNumber = columnNumber * 26 + System.Convert.ToInt32(c) - System.Convert.ToInt32('A') + 1;
- }
- return columnNumber;
- }
- // Converts a cell reference string into the row and column numbers for that cell
- // e.g. G5 -> [row = 5, column = 7]
- private static void GetRowColumn(string cellReference, out int row, out int column)
- {
- row = 0;
- column = 0;
- foreach (char c in cellReference)
- {
- if (Char.IsLetter(c))
- column = column * 26 + System.Convert.ToInt32(c) - System.Convert.ToInt32('A') + 1;
- else
- row = row * 10 + System.Convert.ToInt32(c) - System.Convert.ToInt32('0');
- }
- }
- // Returns the row and column numbers and worksheet part for the named range
- public static WorksheetPart GetRange(SpreadsheetDocument doc, string rangeName, out int startRow, out int startColumn, out int endRow, out int endColumn)
- {
- XDocument book = doc.WorkbookPart.GetXDocument();
- if (book.Root.Element(S.definedNames) == null)
- throw new ArgumentException("Range name not found: " + rangeName);
- XElement element = book.Root.Element(S.definedNames).Elements(S.definedName)
- .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault();
- if (element == null)
- throw new ArgumentException("Range name not found: " + rangeName);
- string sheetName = element.Value.Substring(0, element.Value.IndexOf('!'));
- string range = element.Value.Substring(element.Value.IndexOf('!') + 1).Replace("$","");
- int colonIndex = range.IndexOf(':');
- GetRowColumn(range.Substring(0, colonIndex), out startRow, out startColumn);
- GetRowColumn(range.Substring(colonIndex + 1), out endRow, out endColumn);
- return GetWorksheet(doc, sheetName);
- }
- // Sets the named range with the specified range of row and column numbers
- public static void SetRange(SpreadsheetDocument doc, string rangeName, string sheetName, int startRow, int startColumn, int endRow, int endColumn)
- {
- XDocument book = doc.WorkbookPart.GetXDocument();
- if (book.Root.Element(S.definedNames) == null)
- book.Root.Add(new XElement(S.definedNames));
- XElement element = book.Root.Element(S.definedNames).Elements(S.definedName)
- .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault();
- if (element == null)
- {
- element = new XElement(S.definedName, new XAttribute(NoNamespace.name, rangeName));
- book.Root.Element(S.definedNames).Add(element);
- }
- element.SetValue(String.Format("{0}!${1}${2}:${3}${4}", sheetName, GetColumnId(startColumn), startRow, GetColumnId(endColumn), endRow));
- doc.WorkbookPart.PutXDocument();
- }
- // Sets the end row for the named range
- public static void UpdateRangeEndRow(SpreadsheetDocument doc, string rangeName, int lastRow)
- {
- // Update named range used by pivot table
- XDocument book = doc.WorkbookPart.GetXDocument();
- XElement element = book.Root.Element(S.definedNames).Elements(S.definedName)
- .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault();
- if (element != null)
- {
- string original = element.Value;
- element.SetValue(original.Substring(0, original.Length - 1) + lastRow.ToString());
- }
- doc.WorkbookPart.PutXDocument();
- }
- // Creates an empty row element (r) with the specified row number
- private static XElement CreateEmptyRow(int row)
- {
- return new XElement(S.row, new XAttribute(NoNamespace.r, row.ToString()));
- }
- public static void ForceCalculateOnLoad(SpreadsheetDocument document)
- {
- XDocument book = document.WorkbookPart.GetXDocument();
- XElement element = book.Root.Element(S.calcPr);
- if (element == null)
- {
- book.Root.Add(new XElement(S.calcPr));
- }
- element.SetAttributeValue(NoNamespace.fullCalcOnLoad, "1");
- document.WorkbookPart.PutXDocument();
- }
- public static void FormulaReplaceSheetName(SpreadsheetDocument document, string oldName, string newName)
- {
- foreach (WorksheetPart sheetPart in document.WorkbookPart.WorksheetParts)
- {
- XDocument sheetDoc = sheetPart.GetXDocument();
- bool changed = false;
- foreach (XElement formula in sheetDoc.Descendants(S.f))
- {
- ParseFormula parser = new ParseFormula(formula.Value);
- string newFormula = parser.ReplaceSheetName(oldName, newName);
- if (newFormula != formula.Value)
- {
- formula.SetValue(newFormula);
- changed = true;
- }
- }
- if (changed)
- {
- sheetPart.PutXDocument();
- ForceCalculateOnLoad(document);
- }
- }
- }
- // Copy all cells in the specified range to a new location
- public static void CopyCellRange(SpreadsheetDocument document, WorksheetPart worksheet, int startRow, int startColumn, int endRow, int endColumn,
- int toRow, int toColumn)
- {
- int rowOffset = toRow - startRow;
- int columnOffset = toColumn - startColumn;
- XDocument worksheetXDocument = worksheet.GetXDocument();
- for (int row = startRow; row <= endRow; row++)
- for (int column = startColumn; column <= endColumn; column++)
- {
- XElement oldCell = GetCell(worksheetXDocument, column, row);
- if (oldCell != null)
- {
- XElement newCell = new XElement(oldCell);
- newCell.SetAttributeValue(NoNamespace.r, GetColumnId(column + columnOffset) + (row + rowOffset).ToString());
- XElement formula = newCell.Element(S.f);
- if (formula != null)
- {
- ParseFormula parser = new ParseFormula(formula.Value);
- formula.SetValue(parser.ReplaceRelativeCell(rowOffset, columnOffset));
- }
- SetCell(worksheetXDocument, newCell);
- }
- }
- worksheet.PutXDocument();
- ForceCalculateOnLoad(document);
- }
- // Creates a pivot table in the specified sheet using the specified range name
- // The new pivot table will not be configured with any fields in the rows, columns, filters or values
- public static PivotTablePart CreatePivotTable(SpreadsheetDocument document, string rangeName, WorksheetPart sheet)
- {
- int startRow, startColumn, endRow, endColumn;
- WorksheetPart sourceSheet = GetRange(document, rangeName, out startRow, out startColumn, out endRow, out endColumn);
- // Fill out pivotFields element (for PivotTablePart) and cacheFields element (for PivotTableCacheDefinitionPart)
- // with an element for each column in the source range
- XElement pivotFields = new XElement(S.pivotFields, new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString()));
- XElement cacheFields = new XElement(S.cacheFields, new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString()));
- for (int column = startColumn; column <= endColumn; column++)
- {
- pivotFields.Add(new XElement(S.pivotField, new XAttribute(NoNamespace.showAll, "0")));
- XElement sharedItems = new XElement(S.sharedItems);
- // Determine numeric sharedItems values, if any
- object value = GetCellValue(document, sourceSheet, column, startRow + 1);
- if (value is double || value is Int32)
- {
- bool hasDouble = false;
- double minValue = Convert.ToDouble(value);
- double maxValue = Convert.ToDouble(value);
- if (value is double)
- hasDouble = true;
- for (int row = startRow + 1; row <= endRow; row++)
- {
- value = GetCellValue(document, sourceSheet, column, row);
- if (value is double)
- hasDouble = true;
- if (Convert.ToDouble(value) < minValue)
- minValue = Convert.ToDouble(value);
- if (Convert.ToDouble(value) > maxValue)
- maxValue = Convert.ToDouble(value);
- }
- sharedItems.Add(new XAttribute(NoNamespace.containsSemiMixedTypes, "0"),
- new XAttribute(NoNamespace.containsString, "0"), new XAttribute(NoNamespace.containsNumber, "1"),
- new XAttribute(NoNamespace.minValue, minValue.ToString()), new XAttribute(NoNamespace.maxValue, maxValue.ToString()));
- if (!hasDouble)
- sharedItems.Add(new XAttribute(NoNamespace.containsInteger, "1"));
- }
- cacheFields.Add(new XElement(S.cacheField, new XAttribute(NoNamespace.name, GetCellValue(document, sourceSheet, column, startRow).ToString()),
- new XAttribute(NoNamespace.numFmtId, "0"), sharedItems));
- }
- // Fill out pivotCacheRecords element (for PivotTableCacheRecordsPart) with an element
- // for each row in the source range
- XElement pivotCacheRecords = new XElement(S.pivotCacheRecords, new XAttribute("xmlns", S.s),
- new XAttribute(XNamespace.Xmlns + "r", R.r), new XAttribute(NoNamespace.count, (endRow - startRow).ToString()));
- for (int row = startRow + 1; row <= endRow; row++)
- {
- XElement r = new XElement(S.r);
- // Fill the record element with a value from each column in the source row
- for (int column = startColumn; column <= endColumn; column++)
- {
- object value = GetCellValue(document, sourceSheet, column, row);
- if (value is String)
- r.Add(new XElement(S._s, new XAttribute(NoNamespace.v, value.ToString())));
- else
- r.Add(new XElement(S.n, new XAttribute(NoNamespace.v, value.ToString())));
- }
- pivotCacheRecords.Add(r);
- }
- // Create pivot table parts with proper links
- PivotTablePart pivotTable = sheet.AddNewPart<PivotTablePart>();
- PivotTableCacheDefinitionPart cacheDef = pivotTable.AddNewPart<PivotTableCacheDefinitionPart>();
- PivotTableCacheRecordsPart records = cacheDef.AddNewPart<PivotTableCacheRecordsPart>();
- document.WorkbookPart.AddPart<PivotTableCacheDefinitionPart>(cacheDef);
- // Set content for the PivotTableCacheRecordsPart and PivotTableCacheDefinitionPart
- records.PutXDocument(new XDocument(pivotCacheRecords));
- cacheDef.PutXDocument(new XDocument(new XElement(S.pivotCacheDefinition, new XAttribute("xmlns", S.s),
- new XAttribute(XNamespace.Xmlns + "r", R.r), new XAttribute(R.id, cacheDef.GetIdOfPart(records)),
- new XAttribute(NoNamespace.recordCount, (endRow - startRow).ToString()),
- new XElement(S.cacheSource, new XAttribute(NoNamespace.type, "worksheet"),
- new XElement(S.worksheetSource, new XAttribute(NoNamespace.name, rangeName))),
- cacheFields)));
- // Create the pivotCache entry in the workbook part
- int cacheId = 1;
- XDocument wb = document.WorkbookPart.GetXDocument();
- if (wb.Root.Element(S.pivotCaches) == null)
- wb.Root.Add(new XElement(S.pivotCaches));
- else
- {
- if (wb.Root.Element(S.pivotCaches).Elements(S.pivotCache).Count() != 0)
- cacheId = wb.Root.Element(S.pivotCaches).Elements(S.pivotCache).Max(n => Convert.ToInt32(n.Attribute(NoNamespace.cacheId).Value)) + 1;
- }
- wb.Root.Element(S.pivotCaches).Add(new XElement(S.pivotCache,
- new XAttribute(NoNamespace.cacheId, cacheId),
- new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(cacheDef))));
- document.WorkbookPart.PutXDocument();
- // Set the content for the PivotTablePart
- pivotTable.PutXDocument(new XDocument(new XElement(S.pivotTableDefinition, new XAttribute("xmlns", S.s),
- new XAttribute(NoNamespace.name, "PivotTable1"), new XAttribute(NoNamespace.cacheId, cacheId.ToString()),
- new XAttribute(NoNamespace.dataCaption, "Values"),
- new XElement(S.location, new XAttribute(NoNamespace._ref, "A3:C20"),
- new XAttribute(NoNamespace.firstHeaderRow, "1"), new XAttribute(NoNamespace.firstDataRow, "1"),
- new XAttribute(NoNamespace.firstDataCol, "0")), pivotFields)));
- return pivotTable;
- }
- public enum PivotAxis { Row, Column, Page };
- public static void AddPivotAxis(SpreadsheetDocument document, WorksheetPart sheet, string fieldName, PivotAxis axis)
- {
- // Create indexed items in cache and definition
- PivotTablePart pivotTablePart = sheet.GetPartsOfType<PivotTablePart>().First();
- PivotTableCacheDefinitionPart cacheDefPart = pivotTablePart.GetPartsOfType<PivotTableCacheDefinitionPart>().First();
- PivotTableCacheRecordsPart recordsPart = cacheDefPart.GetPartsOfType<PivotTableCacheRecordsPart>().First();
- XDocument cacheDef = cacheDefPart.GetXDocument();
- int index = Array.FindIndex(cacheDef.Descendants(S.cacheField).ToArray(),
- z => z.Attribute(NoNamespace.name).Value == fieldName);
- XDocument records = recordsPart.GetXDocument();
- List<XElement> values = new List<XElement>();
- foreach (XElement rec in records.Descendants(S.r))
- {
- XElement val = rec.Elements().Skip(index).First();
- int x = Array.FindIndex(values.ToArray(), z => XElement.DeepEquals(z, val));
- if (x == -1)
- {
- values.Add(val);
- x = values.Count() - 1;
- }
- val.ReplaceWith(new XElement(S.x, new XAttribute(NoNamespace.v, x)));
- }
- XElement sharedItems = cacheDef.Descendants(S.cacheField).Skip(index).First().Element(S.sharedItems);
- sharedItems.Add(new XAttribute(NoNamespace.count, values.Count()), values);
- recordsPart.PutXDocument();
- cacheDefPart.PutXDocument();
- // Add axis definition to pivot table field
- XDocument pivotTable = pivotTablePart.GetXDocument();
- XElement pivotField = pivotTable.Descendants(S.pivotField).Skip(index).First();
- XElement items = new XElement(S.items, new XAttribute(NoNamespace.count, values.Count() + 1),
- values.OrderBy(z => z.Attribute(NoNamespace.v).Value).Select(z => new XElement(S.item,
- new XAttribute(NoNamespace.x, Array.FindIndex(values.ToArray(),
- a => a.Attribute(NoNamespace.v).Value == z.Attribute(NoNamespace.v).Value)))));
- items.Add(new XElement(S.item, new XAttribute(NoNamespace.t, "default")));
- switch (axis)
- {
- case PivotAxis.Column:
- pivotField.Add(new XAttribute(NoNamespace.axis, "axisCol"), items);
- // Add to colFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields);
- if (fields == null)
- {
- fields = new XElement(S.colFields, new XAttribute(NoNamespace.count, 0));
- XElement rowFields = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (rowFields == null)
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- else
- rowFields.AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.field, new XAttribute(NoNamespace.x, index)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- case PivotAxis.Row:
- pivotField.Add(new XAttribute(NoNamespace.axis, "axisRow"), items);
- // Add to rowFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (fields == null)
- {
- fields = new XElement(S.rowFields, new XAttribute(NoNamespace.count, 0));
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.field, new XAttribute(NoNamespace.x, index)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- case PivotAxis.Page:
- pivotField.Add(new XAttribute(NoNamespace.axis, "axisPage"), items);
- // Add to pageFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.pageFields);
- if (fields == null)
- {
- fields = new XElement(S.pageFields, new XAttribute(NoNamespace.count, 0));
- XElement prev = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields);
- if (prev == null)
- prev = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (prev == null)
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- else
- prev.AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.pageField, new XAttribute(NoNamespace.fld, index)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- }
- pivotTablePart.PutXDocument();
- ForcePivotRefresh(cacheDefPart);
- }
- public static void AddDataValueLabel(SpreadsheetDocument document, WorksheetPart sheet, PivotAxis axis)
- {
- PivotTablePart pivotTablePart = sheet.GetPartsOfType<PivotTablePart>().First();
- XDocument pivotTable = pivotTablePart.GetXDocument();
- switch (axis)
- {
- case PivotAxis.Column:
- // Add to colFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields);
- if (fields == null)
- {
- fields = new XElement(S.colFields, new XAttribute(NoNamespace.count, 0));
- XElement rowFields = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (rowFields == null)
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- else
- rowFields.AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.field, new XAttribute(NoNamespace.x, -2)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- case PivotAxis.Row:
- // Add to rowFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (fields == null)
- {
- fields = new XElement(S.rowFields, new XAttribute(NoNamespace.count, 0));
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.field, new XAttribute(NoNamespace.x, -2)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- case PivotAxis.Page:
- // Add to pageFields
- {
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.pageFields);
- if (fields == null)
- {
- fields = new XElement(S.pageFields, new XAttribute(NoNamespace.count, 0));
- XElement prev = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields);
- if (prev == null)
- prev = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (prev == null)
- pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields).AddAfterSelf(fields);
- else
- prev.AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.pageField, new XAttribute(NoNamespace.fld, -2)));
- fields.Attribute(NoNamespace.count).Value = fields.Elements(S.field).Count().ToString();
- }
- break;
- }
- pivotTablePart.PutXDocument();
- PivotTableCacheDefinitionPart cacheDefPart = pivotTablePart.GetPartsOfType<PivotTableCacheDefinitionPart>().First();
- ForcePivotRefresh(cacheDefPart);
- }
- public static void AddDataValue(SpreadsheetDocument document, WorksheetPart sheet, string fieldName)
- {
- PivotTablePart pivotTablePart = sheet.GetPartsOfType<PivotTablePart>().First();
- PivotTableCacheDefinitionPart cacheDefPart = pivotTablePart.GetPartsOfType<PivotTableCacheDefinitionPart>().First();
- XDocument cacheDef = cacheDefPart.GetXDocument();
- int index = Array.FindIndex(cacheDef.Descendants(S.cacheField).ToArray(),
- z => z.Attribute(NoNamespace.name).Value == fieldName);
- XDocument pivotTable = pivotTablePart.GetXDocument();
- XElement pivotField = pivotTable.Descendants(S.pivotField).Skip(index).First();
- pivotField.Add(new XAttribute(NoNamespace.dataField, "1"));
- XElement fields = pivotTable.Element(S.pivotTableDefinition).Element(S.dataFields);
- if (fields == null)
- {
- fields = new XElement(S.dataFields, new XAttribute(NoNamespace.count, 0));
- XElement prev = pivotTable.Element(S.pivotTableDefinition).Element(S.pageFields);
- if (prev == null)
- prev = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields);
- if (prev == null)
- prev = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields);
- if (prev == null)
- prev = pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields);
- prev.AddAfterSelf(fields);
- }
- fields.Add(new XElement(S.dataField, new XAttribute(NoNamespace.name, "Sum of " + fieldName),
- new XAttribute(NoNamespace.fld, index), new XAttribute(NoNamespace.baseField, 0),
- new XAttribute(NoNamespace.baseItem, 0)));
- int count = fields.Elements(S.dataField).Count();
- fields.Attribute(NoNamespace.count).Value = count.ToString();
- if (count == 2)
- { // Only when data field count goes from 1 to 2 do we add a special column to label the data fields
- AddDataValueLabel(document, sheet, PivotAxis.Column);
- }
- pivotTablePart.PutXDocument();
- ForcePivotRefresh(cacheDefPart);
- }
- private static void ForcePivotRefresh(PivotTableCacheDefinitionPart cacheDef)
- {
- XDocument doc = cacheDef.GetXDocument();
- XElement def = doc.Element(S.pivotCacheDefinition);
- if (def.Attribute(NoNamespace.refreshOnLoad) == null)
- def.Add(new XAttribute(NoNamespace.refreshOnLoad, 1));
- else
- def.Attribute(NoNamespace.refreshOnLoad).Value = "1";
- cacheDef.PutXDocument();
- }
- public static void CheckNumberFormat(SpreadsheetDocument document, int fmtID, string formatCode)
- {
- XElement numFmt = new XElement(S.numFmt, new XAttribute(NoNamespace.numFmtId, fmtID.ToString()),
- new XAttribute(NoNamespace.formatCode, formatCode));
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- XElement numFmts = styles.Root.Element(S.numFmts);
- if (numFmts == null)
- {
- styles.Root.Element(S.fonts).AddBeforeSelf(new XElement(S.numFmts, new XAttribute(NoNamespace.count, "0")));
- numFmts = styles.Root.Element(S.numFmts);
- }
- int index = Array.FindIndex(numFmts.Elements(S.numFmt).ToArray(),
- z => XElement.DeepEquals(z, numFmt));
- if (index == -1)
- {
- numFmts.Add(numFmt);
- numFmts.Attribute(NoNamespace.count).Value = numFmts.Elements(S.numFmt).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- }
- }
- public class ColorInfo
- {
- public enum ColorType { Theme, Indexed };
- private bool Auto;
- private string RGB;
- private int Indexed;
- private int Theme;
- private double Tint;
- public ColorInfo()
- {
- Auto = true;
- }
- public ColorInfo(ColorType type, int value)
- {
- if (type == ColorType.Indexed)
- Indexed = value;
- else if (type == ColorType.Theme)
- Theme = value;
- }
- public ColorInfo(int theme, double tint)
- {
- Theme = theme;
- Tint = tint;
- }
- public ColorInfo(string rgb)
- {
- RGB = rgb;
- }
- public XElement GetXElement(XName colorName)
- {
- XElement color = new XElement(colorName);
- if (Auto)
- color.Add(new XAttribute(NoNamespace.auto, "1"));
- else if (RGB != null)
- color.Add(new XAttribute(NoNamespace.rgb, RGB));
- else if (Indexed != 0)
- color.Add(new XAttribute(NoNamespace.indexed, Indexed));
- else
- color.Add(new XAttribute(NoNamespace.theme, Theme));
- if (Tint != 0)
- color.Add(new XAttribute(NoNamespace.tint, Tint));
- return color;
- }
- }
- public class Font
- {
- public enum SchemeType { None, Major, Minor };
- public bool Bold { get; set; }
- public ColorInfo Color { get; set; }
- public bool Condense { get; set; }
- public bool Extend { get; set; }
- public int Family { get; set; }
- public bool Italic { get; set; }
- public string Name { get; set; }
- public bool Outline { get; set; }
- public SchemeType Scheme { get; set; }
- public bool Shadow { get; set; }
- public bool StrikeThrough { get; set; }
- public int Size { get; set; }
- public bool Underline { get; set; }
- public XElement GetXElement()
- {
- XElement font = new XElement(S.font);
- if (Bold)
- font.Add(new XElement(S.b));
- if (Italic)
- font.Add(new XElement(S.i));
- if (Underline)
- font.Add(new XElement(S.u));
- if (StrikeThrough)
- font.Add(new XElement(S.strike));
- if (Condense)
- font.Add(new XElement(S.condense));
- if (Extend)
- font.Add(new XElement(S.extend));
- if (Outline)
- font.Add(new XElement(S.outline));
- if (Shadow)
- font.Add(new XElement(S.shadow));
- if (Size != 0)
- font.Add(new XElement(S.sz, new XAttribute(NoNamespace.val, Size.ToString())));
- if (Color != null)
- font.Add(Color.GetXElement(S.color));
- if (Name != null)
- font.Add(new XElement(S.name, new XAttribute(NoNamespace.val, Name)));
- if (Family != 0)
- font.Add(new XElement(S.family, new XAttribute(NoNamespace.val, Family.ToString())));
- switch (Scheme)
- {
- case SchemeType.Major:
- font.Add(new XElement(S.scheme, new XAttribute(NoNamespace.val, "major")));
- break;
- case SchemeType.Minor:
- font.Add(new XElement(S.scheme, new XAttribute(NoNamespace.val, "minor")));
- break;
- }
- return font;
- }
- }
- public static int GetFontIndex(SpreadsheetDocument document, Font f)
- {
- XElement font = f.GetXElement();
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- XElement fonts = styles.Root.Element(S.fonts);
- int index = Array.FindIndex(fonts.Elements(S.font).ToArray(),
- z => XElement.DeepEquals(z, font));
- if (index != -1)
- return index;
- fonts.Add(font);
- fonts.Attribute(NoNamespace.count).Value = fonts.Elements(S.font).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- return fonts.Elements(S.font).Count() - 1;
- }
- public class PatternFill
- {
- public enum PatternType
- {
- None, Solid, DarkDown, DarkGray, DarkGrid, DarkHorizontal, DarkTrellis, DarkUp, DarkVertical,
- Gray0625, Gray125, LightDown, LightGray, LightGrid, LightHorizontal, LightTrellis, LightUp, LightVertical, MediumGray
- };
- private PatternType Pattern;
- private ColorInfo BgColor;
- private ColorInfo FgColor;
- public PatternFill(PatternType pattern, ColorInfo bgColor, ColorInfo fgColor)
- {
- Pattern = pattern;
- BgColor = bgColor;
- FgColor = fgColor;
- }
- public XElement GetXElement()
- {
- XElement pattern = new XElement(S.patternFill);
- switch (Pattern)
- {
- case PatternType.DarkDown:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkDown"));
- break;
- case PatternType.DarkGray:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkGray"));
- break;
- case PatternType.DarkGrid:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkGrid"));
- break;
- case PatternType.DarkHorizontal:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkHorizontal"));
- break;
- case PatternType.DarkTrellis:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkTrellis"));
- break;
- case PatternType.DarkUp:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkUp"));
- break;
- case PatternType.DarkVertical:
- pattern.Add(new XAttribute(NoNamespace.patternType, "darkVertical"));
- break;
- case PatternType.Gray0625:
- pattern.Add(new XAttribute(NoNamespace.patternType, "gray0625"));
- break;
- case PatternType.Gray125:
- pattern.Add(new XAttribute(NoNamespace.patternType, "gray125"));
- break;
- case PatternType.LightDown:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightDown"));
- break;
- case PatternType.LightGray:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightGray"));
- break;
- case PatternType.LightGrid:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightGrid"));
- break;
- case PatternType.LightHorizontal:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightHorizontal"));
- break;
- case PatternType.LightTrellis:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightTrellis"));
- break;
- case PatternType.LightUp:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightUp"));
- break;
- case PatternType.LightVertical:
- pattern.Add(new XAttribute(NoNamespace.patternType, "lightVertical"));
- break;
- case PatternType.MediumGray:
- pattern.Add(new XAttribute(NoNamespace.patternType, "mediumGray"));
- break;
- case PatternType.None:
- pattern.Add(new XAttribute(NoNamespace.patternType, "none"));
- break;
- case PatternType.Solid:
- pattern.Add(new XAttribute(NoNamespace.patternType, "solid"));
- break;
- }
- if (FgColor != null)
- pattern.Add(FgColor.GetXElement(S.fgColor));
- if (BgColor != null)
- pattern.Add(BgColor.GetXElement(S.bgColor));
- return new XElement(S.fill, pattern);
- }
- }
- public class GradientStop
- {
- private double Position;
- private ColorInfo Color;
- public GradientStop(double position, ColorInfo color)
- {
- Position = position;
- Color = color;
- }
- public XElement GetXElement()
- {
- return new XElement(S.stop, new XAttribute(NoNamespace.position, Position), Color.GetXElement(S.color));
- }
- }
- public class GradientFill
- {
- private bool PathGradient;
- private int LinearDegree;
- private double PathTop;
- private double PathLeft;
- private double PathBottom;
- private double PathRight;
- private List<GradientStop> Stops;
- public GradientFill(int degree)
- {
- PathGradient = false;
- LinearDegree = degree;
- Stops = new List<GradientStop>();
- }
- public GradientFill(double top, double left, double bottom, double right)
- {
- PathGradient = true;
- PathTop = top;
- PathLeft = left;
- PathBottom = bottom;
- PathRight = right;
- Stops = new List<GradientStop>();
- }
- public void AddStop(GradientStop stop)
- {
- Stops.Add(stop);
- }
- public XElement GetXElement()
- {
- XElement gradient = new XElement(S.gradientFill);
- if (PathGradient)
- {
- gradient.Add(new XAttribute(NoNamespace.type, "path"),
- new XAttribute(NoNamespace.left, PathLeft.ToString()), new XAttribute(NoNamespace.right, PathRight.ToString()),
- new XAttribute(NoNamespace.top, PathTop.ToString()), new XAttribute(NoNamespace.bottom, PathBottom.ToString()));
- }
- else
- {
- gradient.Add(new XAttribute(NoNamespace.degree, LinearDegree.ToString()));
- }
- foreach (GradientStop stop in Stops)
- gradient.Add(stop.GetXElement());
- return new XElement(S.fill, gradient);
- }
- }
- public static int GetFillIndex(SpreadsheetDocument document, PatternFill patternFill)
- {
- return GetFillIndex(document, patternFill.GetXElement());
- }
- public static int GetFillIndex(SpreadsheetDocument document, GradientFill gradientFill)
- {
- return GetFillIndex(document, gradientFill.GetXElement());
- }
- private static int GetFillIndex(SpreadsheetDocument document, XElement fill)
- {
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- XElement fills = styles.Root.Element(S.fills);
- int index = Array.FindIndex(fills.Elements(S.fill).ToArray(),
- z => XElement.DeepEquals(z, fill));
- if (index != -1)
- return index;
- fills.Add(fill);
- fills.Attribute(NoNamespace.count).Value = fills.Elements(S.fill).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- return fills.Elements(S.fill).Count() - 1;
- }
- public class BorderLine
- {
- public enum LineStyle
- {
- None, DashDot, DashDotDot, Dashed, Dotted, Double, Hair,
- Medium, MediumDashDot, MediumDashDotDot, MediumDashed, SlantDashDot, Thick, Thin
- };
- private LineStyle Style;
- private ColorInfo Color;
- public BorderLine(LineStyle style, ColorInfo color)
- {
- Style = style;
- Color = color;
- }
- public XElement GetXElement(XName name)
- {
- XElement line = new XElement(name);
- switch (Style)
- {
- case LineStyle.DashDot:
- line.Add(new XAttribute(NoNamespace.style, "dashDot"));
- break;
- case LineStyle.DashDotDot:
- line.Add(new XAttribute(NoNamespace.style, "dashDotDot"));
- break;
- case LineStyle.Dashed:
- line.Add(new XAttribute(NoNamespace.style, "dashed"));
- break;
- case LineStyle.Dotted:
- line.Add(new XAttribute(NoNamespace.style, "dotted"));
- break;
- case LineStyle.Double:
- line.Add(new XAttribute(NoNamespace.style, "double"));
- break;
- case LineStyle.Hair:
- line.Add(new XAttribute(NoNamespace.style, "hair"));
- break;
- case LineStyle.Medium:
- line.Add(new XAttribute(NoNamespace.style, "medium"));
- break;
- case LineStyle.MediumDashDot:
- line.Add(new XAttribute(NoNamespace.style, "mediumDashDot"));
- break;
- case LineStyle.MediumDashDotDot:
- line.Add(new XAttribute(NoNamespace.style, "mediumDashDotDot"));
- break;
- case LineStyle.MediumDashed:
- line.Add(new XAttribute(NoNamespace.style, "mediumDashed"));
- break;
- case LineStyle.SlantDashDot:
- line.Add(new XAttribute(NoNamespace.style, "slantDashDot"));
- break;
- case LineStyle.Thick:
- line.Add(new XAttribute(NoNamespace.style, "thick"));
- break;
- case LineStyle.Thin:
- line.Add(new XAttribute(NoNamespace.style, "thin"));
- break;
- }
- line.Add(Color.GetXElement(S.color));
- return line;
- }
- }
- public class Border
- {
- public BorderLine Top { get; set; }
- public BorderLine Bottom { get; set; }
- public BorderLine Left { get; set; }
- public BorderLine Right { get; set; }
- public BorderLine Horizontal { get; set; }
- public BorderLine Vertical { get; set; }
- public BorderLine Diagonal { get; set; }
- public bool DiagonalDown { get; set; }
- public bool DiagonalUp { get; set; }
- public bool Outline { get; set; }
- public XElement GetXElement()
- {
- XElement border = new XElement(S.border);
- if (DiagonalDown)
- border.Add(new XAttribute(NoNamespace.diagonalDown, "1"));
- if (DiagonalUp)
- border.Add(new XAttribute(NoNamespace.diagonalUp, "1"));
- if (Outline)
- border.Add(new XAttribute(NoNamespace.outline, "1"));
- if (Left == null)
- border.Add(new XElement(S.left));
- else
- border.Add(Left.GetXElement(S.left));
- if (Right == null)
- border.Add(new XElement(S.right));
- else
- border.Add(Right.GetXElement(S.right));
- if (Top == null)
- border.Add(new XElement(S.top));
- else
- border.Add(Top.GetXElement(S.top));
- if (Bottom == null)
- border.Add(new XElement(S.bottom));
- else
- border.Add(Bottom.GetXElement(S.bottom));
- if (Diagonal == null)
- border.Add(new XElement(S.diagonal));
- else
- border.Add(Diagonal.GetXElement(S.diagonal));
- if (Horizontal != null)
- border.Add(Horizontal.GetXElement(S.horizontal));
- if (Vertical != null)
- border.Add(Vertical.GetXElement(S.vertical));
- return border;
- }
- }
- public static int GetBorderIndex(SpreadsheetDocument document, Border b)
- {
- XElement border = b.GetXElement();
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- XElement borders = styles.Root.Element(S.borders);
- int index = Array.FindIndex(borders.Elements(S.border).ToArray(),
- z => XElement.DeepEquals(z, border));
- if (index != -1)
- return index;
- borders.Add(border);
- borders.Attribute(NoNamespace.count).Value = borders.Elements(S.border).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- return borders.Elements(S.border).Count() - 1;
- }
- public static int GetStyleIndex(SpreadsheetDocument document, string styleName)
- {
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- string xfId = styles.Root.Element(S.cellStyles).Elements(S.cellStyle)
- .Where(t => t.Attribute(NoNamespace.name).Value == styleName)
- .FirstOrDefault().Attribute(NoNamespace.xfId).Value;
- XElement cellXfs = styles.Root.Element(S.cellXfs);
- int index = Array.FindIndex(cellXfs.Elements(S.xf).ToArray(),
- z => z.Attribute(NoNamespace.xfId).Value == xfId);
- if (index != -1)
- return index;
- XElement cellStyleXf = styles.Root.Element(S.cellStyleXfs).Elements(S.xf).ToArray()[Convert.ToInt32(xfId)];
- if (cellStyleXf != null)
- { // Create new xf element under cellXfs
- cellXfs.Add(new XElement(S.xf, new XAttribute(NoNamespace.numFmtId, cellStyleXf.Attribute(NoNamespace.numFmtId).Value),
- new XAttribute(NoNamespace.fontId, cellStyleXf.Attribute(NoNamespace.fontId).Value),
- new XAttribute(NoNamespace.fillId, cellStyleXf.Attribute(NoNamespace.fillId).Value),
- new XAttribute(NoNamespace.borderId, cellStyleXf.Attribute(NoNamespace.borderId).Value),
- new XAttribute(NoNamespace.xfId, xfId)));
- cellXfs.Attribute(NoNamespace.count).Value = cellXfs.Elements(S.xf).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- return cellXfs.Elements(S.xf).Count() - 1;
- }
- return 0;
- }
- public class CellAlignment
- {
- public enum Horizontal { General, Center, CenterContinuous, Distributed, Fill, Justify, Left, Right };
- public enum Vertical { Bottom, Center, Distributed, Justify, Top };
- public Horizontal HorizontalAlignment { get; set; }
- public int Indent { get; set; }
- public bool JustifyLastLine { get; set; }
- public int ReadingOrder { get; set; }
- public bool ShrinkToFit { get; set; }
- public int TextRotation { get; set; }
- public Vertical VerticalAlignment { get; set; }
- public bool WrapText { get; set; }
- public CellAlignment()
- {
- HorizontalAlignment = Horizontal.General;
- Indent = 0;
- JustifyLastLine = false;
- ReadingOrder = 0;
- ShrinkToFit = false;
- TextRotation = 0;
- VerticalAlignment = Vertical.Bottom;
- WrapText = false;
- }
- public XElement GetXElement()
- {
- XElement align = new XElement(S.alignment);
- switch (HorizontalAlignment)
- {
- case Horizontal.Center:
- align.Add(new XAttribute(NoNamespace.horizontal, "center"));
- break;
- case Horizontal.CenterContinuous:
- align.Add(new XAttribute(NoNamespace.horizontal, "centerContinuous"));
- break;
- case Horizontal.Distributed:
- align.Add(new XAttribute(NoNamespace.horizontal, "distributed"));
- break;
- case Horizontal.Fill:
- align.Add(new XAttribute(NoNamespace.horizontal, "fill"));
- break;
- case Horizontal.Justify:
- align.Add(new XAttribute(NoNamespace.horizontal, "justify"));
- break;
- case Horizontal.Left:
- align.Add(new XAttribute(NoNamespace.horizontal, "left"));
- break;
- case Horizontal.Right:
- align.Add(new XAttribute(NoNamespace.horizontal, "right"));
- break;
- }
- if (Indent != 0)
- align.Add(new XAttribute(NoNamespace.indent, Indent));
- if (JustifyLastLine)
- align.Add(new XAttribute(NoNamespace.justifyLastLine, true));
- if (ReadingOrder != 0)
- align.Add(new XAttribute(NoNamespace.readingOrder, ReadingOrder));
- if (ShrinkToFit)
- align.Add(new XAttribute(NoNamespace.shrinkToFit, true));
- if (TextRotation != 0)
- align.Add(new XAttribute(NoNamespace.textRotation, TextRotation));
- switch (VerticalAlignment)
- {
- case Vertical.Center:
- align.Add(new XAttribute(NoNamespace.vertical, "center"));
- break;
- case Vertical.Distributed:
- align.Add(new XAttribute(NoNamespace.vertical, "distributed"));
- break;
- case Vertical.Justify:
- align.Add(new XAttribute(NoNamespace.vertical, "justify"));
- break;
- case Vertical.Top:
- align.Add(new XAttribute(NoNamespace.vertical, "top"));
- break;
- }
- if (WrapText)
- align.Add(new XAttribute(NoNamespace.wrapText, true));
- return align;
- }
- }
- public static int GetStyleIndex(SpreadsheetDocument document, int numFmt, int font, int fill, int border, CellAlignment alignment, bool hidden, bool locked)
- {
- XElement xf = new XElement(S.xf, new XAttribute(NoNamespace.numFmtId, numFmt),
- new XAttribute(NoNamespace.fontId, font), new XAttribute(NoNamespace.fillId, fill),
- new XAttribute(NoNamespace.borderId, border), new XAttribute(NoNamespace.xfId, 0),
- new XAttribute(NoNamespace.applyNumberFormat, (numFmt == 0) ? 0 : 1),
- new XAttribute(NoNamespace.applyFont, (font == 0) ? 0 : 1),
- new XAttribute(NoNamespace.applyFill, (fill == 0) ? 0 : 1),
- new XAttribute(NoNamespace.applyBorder, (border == 0) ? 0 : 1));
- if (alignment != null)
- {
- xf.Add(new XAttribute(NoNamespace.applyAlignment, "1"));
- xf.Add(alignment.GetXElement());
- }
- else
- xf.Add(new XAttribute(NoNamespace.applyAlignment, "0"));
- if (hidden || locked)
- {
- XElement prot = new XElement(S.protection);
- if (hidden)
- prot.Add(new XAttribute(NoNamespace.hidden, true));
- if (locked)
- prot.Add(new XAttribute(NoNamespace.locked, true));
- xf.Add(prot);
- xf.Add(new XAttribute(NoNamespace.applyProtection, "1"));
- }
- else
- xf.Add(new XAttribute(NoNamespace.applyProtection, "0"));
- XDocument styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument();
- XElement cellXfs = styles.Root.Element(S.cellXfs);
- int index = Array.FindIndex(cellXfs.Elements(S.xf).ToArray(),
- z => XElement.DeepEquals(z, xf));
- if (index != -1)
- return index;
- cellXfs.Add(xf);
- cellXfs.Attribute(NoNamespace.count).Value = cellXfs.Elements(S.xf).Count().ToString();
- document.WorkbookPart.WorkbookStylesPart.PutXDocument();
- return cellXfs.Elements(S.xf).Count() - 1;
- }
- public static void CreateDefaultStyles(SpreadsheetDocument document)
- {
- // Create the style part
- WorkbookStylesPart stylesPart = document.WorkbookPart.AddNewPart<WorkbookStylesPart>();
- stylesPart.PutXDocument(new XDocument(XElement.Parse(
- @"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
- <styleSheet xmlns='http://schemas.openxmlformats.org/spreadsheetml/2006/main'>
- <fonts count='18'>
- <font>
- <sz val='11'/>
- <color theme='1'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color theme='1'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='18'/>
- <color theme='3'/>
- <name val='Cambria'/>
- <family val='2'/>
- <scheme val='major'/>
- </font>
- <font>
- <b/>
- <sz val='15'/>
- <color theme='3'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='13'/>
- <color theme='3'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='11'/>
- <color theme='3'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FF006100'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FF9C0006'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FF9C6500'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FF3F3F76'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='11'/>
- <color rgb='FF3F3F3F'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='11'/>
- <color rgb='FFFA7D00'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FFFA7D00'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='11'/>
- <color theme='0'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color rgb='FFFF0000'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <i/>
- <sz val='11'/>
- <color rgb='FF7F7F7F'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <b/>
- <sz val='11'/>
- <color theme='1'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- <font>
- <sz val='11'/>
- <color theme='0'/>
- <name val='Calibri'/>
- <family val='2'/>
- <scheme val='minor'/>
- </font>
- </fonts>
- <fills count='33'>
- <fill>
- <patternFill patternType='none'/>
- </fill>
- <fill>
- <patternFill patternType='gray125'/>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFC6EFCE'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFFFC7CE'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFFFEB9C'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFFFCC99'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFF2F2F2'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFA5A5A5'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor rgb='FFFFFFCC'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='4'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='4' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='4' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='4' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='5'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='5' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='5' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='5' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='6'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='6' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='6' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='6' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='7'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='7' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='7' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='7' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='8'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='8' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='8' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='8' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='9'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='9' tint='0.79998168889431442'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='9' tint='0.59999389629810485'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- <fill>
- <patternFill patternType='solid'>
- <fgColor theme='9' tint='0.39997558519241921'/>
- <bgColor indexed='65'/>
- </patternFill>
- </fill>
- </fills>
- <borders count='10'>
- <border>
- <left/>
- <right/>
- <top/>
- <bottom/>
- <diagonal/>
- </border>
- <border>
- <left/>
- <right/>
- <top/>
- <bottom style='thick'>
- <color theme='4'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left/>
- <right/>
- <top/>
- <bottom style='thick'>
- <color theme='4' tint='0.499984740745262'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left/>
- <right/>
- <top/>
- <bottom style='medium'>
- <color theme='4' tint='0.39997558519241921'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left style='thin'>
- <color rgb='FF7F7F7F'/>
- </left>
- <right style='thin'>
- <color rgb='FF7F7F7F'/>
- </right>
- <top style='thin'>
- <color rgb='FF7F7F7F'/>
- </top>
- <bottom style='thin'>
- <color rgb='FF7F7F7F'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left style='thin'>
- <color rgb='FF3F3F3F'/>
- </left>
- <right style='thin'>
- <color rgb='FF3F3F3F'/>
- </right>
- <top style='thin'>
- <color rgb='FF3F3F3F'/>
- </top>
- <bottom style='thin'>
- <color rgb='FF3F3F3F'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left/>
- <right/>
- <top/>
- <bottom style='double'>
- <color rgb='FFFF8001'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left style='double'>
- <color rgb='FF3F3F3F'/>
- </left>
- <right style='double'>
- <color rgb='FF3F3F3F'/>
- </right>
- <top style='double'>
- <color rgb='FF3F3F3F'/>
- </top>
- <bottom style='double'>
- <color rgb='FF3F3F3F'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left style='thin'>
- <color rgb='FFB2B2B2'/>
- </left>
- <right style='thin'>
- <color rgb='FFB2B2B2'/>
- </right>
- <top style='thin'>
- <color rgb='FFB2B2B2'/>
- </top>
- <bottom style='thin'>
- <color rgb='FFB2B2B2'/>
- </bottom>
- <diagonal/>
- </border>
- <border>
- <left/>
- <right/>
- <top style='thin'>
- <color theme='4'/>
- </top>
- <bottom style='double'>
- <color theme='4'/>
- </bottom>
- <diagonal/>
- </border>
- </borders>
- <cellStyleXfs count='42'>
- <xf numFmtId='0' fontId='0' fillId='0' borderId='0'/>
- <xf numFmtId='0' fontId='2' fillId='0' borderId='0' applyNumberFormat='0' applyFill='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='3' fillId='0' borderId='1' applyNumberFormat='0' applyFill='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='4' fillId='0' borderId='2' applyNumberFormat='0' applyFill='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='5' fillId='0' borderId='3' applyNumberFormat='0' applyFill='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='5' fillId='0' borderId='0' applyNumberFormat='0' applyFill='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='6' fillId='2' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='7' fillId='3' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='8' fillId='4' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='9' fillId='5' borderId='4' applyNumberFormat='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='10' fillId='6' borderId='5' applyNumberFormat='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='11' fillId='6' borderId='4' applyNumberFormat='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='12' fillId='0' borderId='6' applyNumberFormat='0' applyFill='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='13' fillId='7' borderId='7' applyNumberFormat='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='14' fillId='0' borderId='0' applyNumberFormat='0' applyFill='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='8' borderId='8' applyNumberFormat='0' applyFont='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='15' fillId='0' borderId='0' applyNumberFormat='0' applyFill='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='16' fillId='0' borderId='9' applyNumberFormat='0' applyFill='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='9' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='10' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='11' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='12' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='13' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='14' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='15' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='16' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='17' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='18' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='19' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='20' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='21' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='22' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='23' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='24' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='25' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='26' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='27' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='28' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='29' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='30' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='1' fillId='31' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- <xf numFmtId='0' fontId='17' fillId='32' borderId='0' applyNumberFormat='0' applyBorder='0' applyAlignment='0' applyProtection='0'/>
- </cellStyleXfs>
- <cellXfs count='1'>
- <xf numFmtId='0' fontId='0' fillId='0' borderId='0' xfId='0'/>
- </cellXfs>
- <cellStyles count='42'>
- <cellStyle name='20% - Accent1' xfId='19' builtinId='30' customBuiltin='1'/>
- <cellStyle name='20% - Accent2' xfId='23' builtinId='34' customBuiltin='1'/>
- <cellStyle name='20% - Accent3' xfId='27' builtinId='38' customBuiltin='1'/>
- <cellStyle name='20% - Accent4' xfId='31' builtinId='42' customBuiltin='1'/>
- <cellStyle name='20% - Accent5' xfId='35' builtinId='46' customBuiltin='1'/>
- <cellStyle name='20% - Accent6' xfId='39' builtinId='50' customBuiltin='1'/>
- <cellStyle name='40% - Accent1' xfId='20' builtinId='31' customBuiltin='1'/>
- <cellStyle name='40% - Accent2' xfId='24' builtinId='35' customBuiltin='1'/>
- <cellStyle name='40% - Accent3' xfId='28' builtinId='39' customBuiltin='1'/>
- <cellStyle name='40% - Accent4' xfId='32' builtinId='43' customBuiltin='1'/>
- <cellStyle name='40% - Accent5' xfId='36' builtinId='47' customBuiltin='1'/>
- <cellStyle name='40% - Accent6' xfId='40' builtinId='51' customBuiltin='1'/>
- <cellStyle name='60% - Accent1' xfId='21' builtinId='32' customBuiltin='1'/>
- <cellStyle name='60% - Accent2' xfId='25' builtinId='36' customBuiltin='1'/>
- <cellStyle name='60% - Accent3' xfId='29' builtinId='40' customBuiltin='1'/>
- <cellStyle name='60% - Accent4' xfId='33' builtinId='44' customBuiltin='1'/>
- <cellStyle name='60% - Accent5' xfId='37' builtinId='48' customBuiltin='1'/>
- <cellStyle name='60% - Accent6' xfId='41' builtinId='52' customBuiltin='1'/>
- <cellStyle name='Accent1' xfId='18' builtinId='29' customBuiltin='1'/>
- <cellStyle name='Accent2' xfId='22' builtinId='33' customBuiltin='1'/>
- <cellStyle name='Accent3' xfId='26' builtinId='37' customBuiltin='1'/>
- <cellStyle name='Accent4' xfId='30' builtinId='41' customBuiltin='1'/>
- <cellStyle name='Accent5' xfId='34' builtinId='45' customBuiltin='1'/>
- <cellStyle name='Accent6' xfId='38' builtinId='49' customBuiltin='1'/>
- <cellStyle name='Bad' xfId='7' builtinId='27' customBuiltin='1'/>
- <cellStyle name='Calculation' xfId='11' builtinId='22' customBuiltin='1'/>
- <cellStyle name='Check Cell' xfId='13' builtinId='23' customBuiltin='1'/>
- <cellStyle name='Explanatory Text' xfId='16' builtinId='53' customBuiltin='1'/>
- <cellStyle name='Good' xfId='6' builtinId='26' customBuiltin='1'/>
- <cellStyle name='Heading 1' xfId='2' builtinId='16' customBuiltin='1'/>
- <cellStyle name='Heading 2' xfId='3' builtinId='17' customBuiltin='1'/>
- <cellStyle name='Heading 3' xfId='4' builtinId='18' customBuiltin='1'/>
- <cellStyle name='Heading 4' xfId='5' builtinId='19' customBuiltin='1'/>
- <cellStyle name='Input' xfId='9' builtinId='20' customBuiltin='1'/>
- <cellStyle name='Linked Cell' xfId='12' builtinId='24' customBuiltin='1'/>
- <cellStyle name='Neutral' xfId='8' builtinId='28' customBuiltin='1'/>
- <cellStyle name='Normal' xfId='0' builtinId='0'/>
- <cellStyle name='Note' xfId='15' builtinId='10' customBuiltin='1'/>
- <cellStyle name='Output' xfId='10' builtinId='21' customBuiltin='1'/>
- <cellStyle name='Title' xfId='1' builtinId='15' customBuiltin='1'/>
- <cellStyle name='Total' xfId='17' builtinId='25' customBuiltin='1'/>
- <cellStyle name='Warning Text' xfId='14' builtinId='11' customBuiltin='1'/>
- </cellStyles>
- <dxfs count='0'/>
- <tableStyles count='0' defaultTableStyle='TableStyleMedium9' defaultPivotStyle='PivotStyleLight16'/>
- </styleSheet>")));
- }
- /// <summary>
- /// Creates a worksheet document and inserts data into it
- /// </summary>
- /// <param name="headerList">List of values that will act as the header</param>
- /// <param name="valueTable">Values for worksheet content</param>
- /// <param name="headerRow">Header row</param>
- /// <returns></returns>
- internal static WorksheetPart Create(SpreadsheetDocument document, List<string> headerList, string[][] valueTable, int headerRow)
- {
- XDocument xDocument = CreateEmptyWorksheet();
-
- for (int i = 0; i < headerList.Count; i++)
- {
- AddValue(xDocument, headerRow, i + 1, headerList[i]);
- }
- int rows = valueTable.GetLength(0);
- int cols = valueTable[0].GetLength(0);
- for (int i = 0; i < rows; i++)
- {
- for (int j = 0; j < cols; j++)
- {
- AddValue(xDocument, i + headerRow + 1, j + 1, valueTable[i][j]);
- }
- }
- WorksheetPart part = Add(document, xDocument);
- return part;
- }
- /// <summary>
- /// Creates element structure needed to describe an empty worksheet
- /// </summary>
- /// <returns>Document with contents for an empty worksheet</returns>
- private static XDocument CreateEmptyWorksheet()
- {
- XDocument document =
- new XDocument(
- new XElement(ns + "worksheet",
- new XAttribute("xmlns", ns),
- new XAttribute(XNamespace.Xmlns + "r", relationshipsns),
- new XElement(ns + "sheetData")
- )
- );
- return document;
- }
- /// <summary>
- /// Adds a value to a cell inside a worksheet document
- /// </summary>
- /// <param name="worksheet">document to add values</param>
- /// <param name="row">Row</param>
- /// <param name="column">Column</param>
- /// <param name="value">Value to add</param>
- private static void AddValue(XDocument worksheet, int row, int column, string value)
- {
- //Set the cell reference
- string cellReference = GetColumnId(column) + row.ToString();
- double numericValue;
- //Determining if value for cell is text or numeric
- bool valueIsNumeric = double.TryParse(value, out numericValue);
- //Creating the new cell element (markup)
- XElement newCellXElement = valueIsNumeric ?
- new XElement(ns + "c",
- new XAttribute("r", cellReference),
- new XElement(ns + "v", numericValue)
- )
- :
- new XElement(ns + "c",
- new XAttribute("r", cellReference),
- new XAttribute("t", "inlineStr"),
- new XElement(ns + "is",
- new XElement(ns + "t", value)
- )
- );
- // Find the row containing the cell to add the value to
- XName rowName = "r";
- XElement rowElement =
- worksheet.Root
- .Element(ns + "sheetData")
- .Elements(ns + "row")
- .Where(
- t => t.Attribute(rowName).Value == row.ToString()
- )
- .FirstOrDefault();
- if (rowElement == null)
- {
- //row element does not exist
- //create a new one
- rowElement = CreateEmptyRow(row);
- //row elements must appear in order inside sheetData element
- if (worksheet.Root
- .Element(ns + "sheetData").HasElements)
- { //if there are more rows already defined at sheetData element
- //find the row with the inmediate higher index for the row containing the cell to set the value to
- XElement rowAfterElement = FindRowAfter(worksheet, row);
- //if there is a row with an inmediate higher index already defined at sheetData
- if (rowAfterElement != null)
- {
- //add the new row before the row with an inmediate higher index
- rowAfterElement.AddBeforeSelf(rowElement);
- }
- else
- { //this row is going to be the one with the highest index (add it as the last element for sheetData)
- worksheet.Root.Element(ns + "sheetData").Elements(ns + "row").Last().AddAfterSelf(rowElement);
- }
- }
- else
- { //there are no other rows already defined at sheetData
- //Add a new row elemento to sheetData
- worksheet
- .Root
- .Element(ns + "sheetData")
- .Add(
- rowElement //= CreateEmptyRow(row)
- );
- }
- //Add the new cell to the row Element
- rowElement.Add(newCellXElement);
- }
- else
- {
- //row containing the cell to set the value to is already defined at sheetData
- //look if cell already exist at that row
- XElement currentCellXElement = rowElement
- .Elements(ns + "c")
- .Where(
- t => t.Attribute("r").Value == cellReference
- ).FirstOrDefault();
- if (currentCellXElement == null)
- { //cell element does not exist at row indicated as parameter
- //find the inmediate right column for the cell to set the value to
- XElement columnAfterXElement = FindColumAfter(worksheet, row, column);
- if (columnAfterXElement != null)
- {
- //Insert the new cell before the inmediate right column
- columnAfterXElement.AddBeforeSelf(newCellXElement);
- }
- else
- { //There is no inmediate right cell
- //Add the new cell as the last element for the row
- rowElement.Add(newCellXElement);
- }
- }
- else
- {
- //cell alreay exist
- //replace the current cell with that with the new value
- currentCellXElement.ReplaceWith(newCellXElement);
- }
- }
- }
- /// <summary>
- /// Adds a given worksheet to the document
- /// </summary>
- /// <param name="worksheet">Worksheet document to add</param>
- /// <returns>Worksheet part just added</returns>
- public static WorksheetPart Add(SpreadsheetDocument doc, XDocument worksheet)
- {
- // Associates base content to a new worksheet part
- WorkbookPart workbook = doc.WorkbookPart;
- WorksheetPart worksheetPart = workbook.AddNewPart<WorksheetPart>();
- worksheetPart.PutXDocument(worksheet);
- // Associates the worksheet part to the workbook part
- XDocument document = doc.WorkbookPart.GetXDocument();
- int sheetId =
- document.Root
- .Element(ns + "sheets")
- .Elements(ns + "sheet")
- .Count() + 1;
- int worksheetCount =
- document.Root
- .Element(ns + "sheets")
- .Elements(ns + "sheet")
- .Where(
- t =>
- t.Attribute("name").Value.StartsWith("sheet", StringComparison.OrdinalIgnoreCase)
- )
- .Count() + 1;
- // Adds content to workbook document to reference worksheet document
- document.Root
- .Element(ns + "sheets")
- .Add(
- new XElement(ns + "sheet",
- new XAttribute("name", string.Format("sheet{0}", worksheetCount)),
- new XAttribute("sheetId", sheetId),
- new XAttribute(relationshipsns + "id", workbook.GetIdOfPart(worksheetPart))
- )
- );
- doc.WorkbookPart.PutXDocument();
- return worksheetPart;
- }
- }
- }
|