123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- // 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.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Xml.Linq;
- using DocumentFormat.OpenXml.Packaging;
- using System.IO;
- namespace OpenXmlPowerTools
- {
- public class Table
- {
- public int Id { get; set; }
- public string TableName { get; set; }
- public string DisplayName { get; set; }
- public XElement TableStyleInfo { get; set; }
- public string Ref { get; set; }
- public int LeftColumn { get; set; }
- public int RightColumn { get; set; }
- public int TopRow { get; set; }
- public int BottomRow { get; set; }
- public int? HeaderRowCount { get; set; }
- public int? TotalsRowCount { get; set; }
- public string TableType { get; set; } // external data query, data in worksheet, or XML data
- public TableDefinitionPart TableDefinitionPart { get; set; }
- public WorksheetPart Parent { get; set; }
- public Table(WorksheetPart parent) { Parent = parent; }
- public IEnumerable<TableColumn> TableColumns()
- {
- XNamespace x = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
- return TableDefinitionPart
- .GetXDocument()
- .Root
- .Element(x + "tableColumns")
- .Elements(x + "tableColumn")
- .Select((c, i) =>
- new TableColumn(this)
- {
- Id = (int)c.Attribute("id"),
- ColumnNumber = this.LeftColumn + i,
- Name = (string)c.Attribute("name"),
- DataDxfId = (int?)c.Attribute("dataDxfId"),
- QueryTableFieldId = (int?)c.Attribute("queryTableFieldId"),
- UniqueName = (string)c.Attribute("uniqueName"),
- ColumnIndex = i,
- }
- );
- }
- public IEnumerable<TableRow> TableRows()
- {
- string refStart = Ref.Split(':').First();
- int rowStart = Int32.Parse(XlsxTables.SplitAddress(refStart)[1]);
- string refEnd = Ref.Split(':').ElementAt(1);
- int rowEnd = Int32.Parse(XlsxTables.SplitAddress(refEnd)[1]);
- int headerRowsCount = HeaderRowCount == null ? 0 : (int)HeaderRowCount;
- int totalRowsCount = TotalsRowCount == null ? 0 : (int)TotalsRowCount;
- return Parent
- .Rows()
- .Skip(headerRowsCount)
- .SkipLast(totalRowsCount)
- .Where(r =>
- {
- int rowId = Int32.Parse(r.RowId);
- return rowId >= rowStart && rowId <= rowEnd;
- }
- )
- .Select(r => new TableRow(this) { Row = r });
- }
- }
- public class TableColumn
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public int? DataDxfId { get; set; }
- public int? QueryTableFieldId { get; set; }
- public string UniqueName { get; set; }
- public int ColumnNumber { get; set; }
- public int ColumnIndex { get; set; }
- public Table Parent { get; set; }
- public TableColumn(Table parent) { Parent = parent; }
- }
- public class TableRow
- {
- public Row Row { get; set; }
- public Table Parent { get; set; }
- public TableRow(Table parent) { Parent = parent; }
- public TableCell this[string columnName]
- {
- get
- {
- TableColumn tc = Parent
- .TableColumns()
- .Where(x => x.Name.ToLower() == columnName.ToLower())
- .FirstOrDefault();
- if (tc == null)
- throw new Exception("Invalid column name: " + columnName);
- string[] refs = Parent.Ref.Split(':');
- string[] startRefs = XlsxTables.SplitAddress(refs[0]);
- string columnAddress = XlsxTables.IndexToColumnAddress(XlsxTables.ColumnAddressToIndex(startRefs[0]) + tc.ColumnIndex);
- Cell cell = Row.Cells().Where(c => c.ColumnAddress == columnAddress).FirstOrDefault();
- if (cell != null)
- {
- if (cell.Type == "s")
- return new TableCell(cell.SharedString);
- else
- return new TableCell(cell.Value);
- }
- else
- return new TableCell("");
- }
- }
- }
- public class TableCell : IEquatable<TableCell>
- {
- public string Value { get; set; }
- public TableCell(string v)
- {
- Value = v;
- }
- public override string ToString()
- {
- return Value;
- }
- public override bool Equals(object obj)
- {
- return this.Value == ((TableCell)obj).Value;
- }
- bool IEquatable<TableCell>.Equals(TableCell other)
- {
- return this.Value == other.Value;
- }
- public override int GetHashCode()
- {
- return this.Value.GetHashCode();
- }
- public static bool operator ==(TableCell left, TableCell right)
- {
- if ((object)left != (object)right) return false;
- return left.Value == right.Value;
- }
- public static bool operator !=(TableCell left, TableCell right)
- {
- if ((object)left != (object)right) return false;
- return left.Value != right.Value;
- }
- public static explicit operator string(TableCell cell)
- {
- if (cell == null) return null;
- return cell.Value;
- }
- public static explicit operator bool(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return cell.Value == "1";
- }
- public static explicit operator bool?(TableCell cell)
- {
- if (cell == null) return null;
- return cell.Value == "1";
- }
- public static explicit operator int(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return Int32.Parse(cell.Value);
- }
- public static explicit operator int?(TableCell cell)
- {
- if (cell == null) return null;
- return Int32.Parse(cell.Value);
- }
- public static explicit operator uint(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return UInt32.Parse(cell.Value);
- }
- public static explicit operator uint?(TableCell cell)
- {
- if (cell == null) return null;
- return UInt32.Parse(cell.Value);
- }
- public static explicit operator long(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return Int64.Parse(cell.Value);
- }
- public static explicit operator long?(TableCell cell)
- {
- if (cell == null) return null;
- return Int64.Parse(cell.Value);
- }
- public static explicit operator ulong(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return UInt64.Parse(cell.Value);
- }
- public static explicit operator ulong?(TableCell cell)
- {
- if (cell == null) return null;
- return UInt64.Parse(cell.Value);
- }
- public static explicit operator float(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return Single.Parse(cell.Value);
- }
- public static explicit operator float?(TableCell cell)
- {
- if (cell == null) return null;
- return Single.Parse(cell.Value);
- }
- public static explicit operator double(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return Double.Parse(cell.Value);
- }
- public static explicit operator double?(TableCell cell)
- {
- if (cell == null) return null;
- return Double.Parse(cell.Value);
- }
- public static explicit operator decimal(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return Decimal.Parse(cell.Value);
- }
- public static explicit operator decimal?(TableCell cell)
- {
- if (cell == null) return null;
- return Decimal.Parse(cell.Value);
- }
- public static implicit operator DateTime(TableCell cell)
- {
- if (cell == null) throw new ArgumentNullException("TableCell");
- return new DateTime(1900, 1, 1).AddDays(Int32.Parse(cell.Value) - 2);
- }
- public static implicit operator DateTime?(TableCell cell)
- {
- if (cell == null) return null;
- return new DateTime(1900, 1, 1).AddDays(Int32.Parse(cell.Value) - 2);
- }
- }
- public class Row
- {
- public XElement RowElement { get; set; }
- public string RowId { get; set; }
- public string Spans { get; set; }
- public List<Cell> Cells()
- {
- XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
- SpreadsheetDocument doc = (SpreadsheetDocument)Parent.OpenXmlPackage;
- SharedStringTablePart sharedStringTable = doc.WorkbookPart.SharedStringTablePart;
- IEnumerable<XElement> cells = this.RowElement.Elements(S.c);
- var r = cells
- .Select(cell => {
- var cellType = (string)cell.Attribute("t");
- var sharedString = cellType == "s" ?
- sharedStringTable
- .GetXDocument()
- .Root
- .Elements(s + "si")
- .Skip((int)cell.Element(s + "v"))
- .First()
- .Descendants(s + "t")
- .StringConcatenate(e => (string)e)
- : null;
- var column = (string)cell.Attribute("r");
- var columnAddress = column.Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9').First();
- var columnIndex = XlsxTables.ColumnAddressToIndex(columnAddress);
- var newCell = new Cell(this)
- {
- CellElement = cell,
- Row = (string)RowElement.Attribute("r"),
- Column = column,
- ColumnAddress = columnAddress,
- ColumnIndex = columnIndex,
- Type = cellType,
- Formula = (string)cell.Element(S.f),
- Style = (int?)cell.Attribute("s"),
- Value = (string)cell.Element(S.v),
- SharedString = sharedString
- };
- return newCell;
- });
- var ra = r.ToList();
- return ra;
- }
- public WorksheetPart Parent { get; set; }
- public Row(WorksheetPart parent) { Parent = parent; }
- }
- public class Cell
- {
- public XElement CellElement { get; set; }
- public string Row { get; set; }
- public string Column { get; set; }
- public string ColumnAddress { get; set; }
- public int ColumnIndex { get; set; }
- public string Type { get; set; }
- public string Value { get; set; }
- public string Formula { get; set; }
- public int? Style { get; set; }
- public string SharedString { get; set; }
- public Row Parent { get; set; }
- public Cell(Row parent) { Parent = parent; }
- }
- public static class XlsxTables
- {
- public static IEnumerable<Table> Tables(this SpreadsheetDocument spreadsheet)
- {
- foreach (var worksheetPart in spreadsheet.WorkbookPart.WorksheetParts)
- foreach (var table in worksheetPart.TableDefinitionParts)
- {
- XDocument tableDefDoc = table.GetXDocument();
- Table t = new Table(worksheetPart)
- {
- Id = (int)tableDefDoc.Root.Attribute("id"),
- TableName = (string)tableDefDoc.Root.Attribute("name"),
- DisplayName = (string)tableDefDoc.Root.Attribute("displayName"),
- TableStyleInfo = tableDefDoc.Root.Element(S.tableStyleInfo),
- Ref = (string)tableDefDoc.Root.Attribute("ref"),
- TotalsRowCount = (int?)tableDefDoc.Root.Attribute("totalsRowCount"),
- //HeaderRowCount = (int?)tableDefDoc.Root.Attribute("headerRowCount"),
- HeaderRowCount = 1, // currently there always is a header row
- TableType = (string)tableDefDoc.Root.Attribute("tableType"),
- TableDefinitionPart = table
- };
- int leftColumn, topRow, rightColumn, bottomRow;
- ParseRange(t.Ref, out leftColumn, out topRow, out rightColumn, out bottomRow);
- t.LeftColumn = leftColumn;
- t.TopRow = topRow;
- t.RightColumn = rightColumn;
- t.BottomRow = bottomRow;
- yield return t;
- }
- }
- public static void ParseRange(string theRef, out int leftColumn, out int topRow, out int rightColumn, out int bottomRow)
- {
- // C5:E7
- var spl = theRef.Split(':');
- string refStart = spl.First();
- var refStartSplit = XlsxTables.SplitAddress(refStart);
- leftColumn = XlsxTables.ColumnAddressToIndex(refStartSplit[0]);
- topRow = Int32.Parse(refStartSplit[1]);
- string refEnd = spl.ElementAt(1);
- var refEndSplit = XlsxTables.SplitAddress(refEnd);
- rightColumn = XlsxTables.ColumnAddressToIndex(refEndSplit[0]);
- bottomRow = Int32.Parse(refEndSplit[1]);
- }
- public static Table Table(this SpreadsheetDocument spreadsheet,
- string tableName)
- {
- return spreadsheet.Tables().Where(t => t.TableName.ToLower() == tableName.ToLower()).FirstOrDefault();
- }
- public static IEnumerable<Row> Rows(this WorksheetPart worksheetPart)
- {
- XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
- var rows = worksheetPart
- .GetXDocument()
- .Root
- .Elements(S.sheetData)
- .Elements(S.row)
- .Select(r =>
- {
- var row = new Row(worksheetPart)
- {
- RowElement = r,
- RowId = (string)r.Attribute("r"),
- Spans = (string)r.Attribute("spans")
- };
- return row;
- });
- return rows;
- }
- public static string[] SplitAddress(string address)
- {
- int i;
- for (i = 0; i < address.Length; i++)
- if (address[i] >= '0' && address[i] <= '9')
- break;
- if (i == address.Length)
- throw new FileFormatException("Invalid spreadsheet. Bad cell address.");
- return new[] {
- address.Substring(0, i),
- address.Substring(i)
- };
- }
- public static string IndexToColumnAddress(int index)
- {
- if (index < 26)
- {
- char c = (char)((int)'A' + index);
- string s = new string(c, 1);
- return s;
- }
- if (index < 702)
- {
- int i = index - 26;
- int i1 = (int)(i / 26);
- int i2 = i % 26;
- string s = new string((char)((int)'A' + i1), 1) +
- new string((char)((int)'A' + i2), 1);
- return s;
- }
- if (index < 18278)
- {
- int i = index - 702;
- int i1 = (int)(i / 676);
- i = i - i1 * 676;
- int i2 = (int)(i / 26);
- int i3 = i % 26;
- string s = new string((char)((int)'A' + i1), 1) +
- new string((char)((int)'A' + i2), 1) +
- new string((char)((int)'A' + i3), 1);
- return s;
- }
- throw new Exception("Invalid column address");
- }
- public static int ColumnAddressToIndex(string columnAddress)
- {
- if (columnAddress.Length == 1)
- {
- char c = columnAddress[0];
- int i = c - 'A';
- return i;
- }
- if (columnAddress.Length == 2)
- {
- char c1 = columnAddress[0];
- char c2 = columnAddress[1];
- int i1 = c1 - 'A';
- int i2 = c2 - 'A';
- return (i1 + 1) * 26 + i2;
- }
- if (columnAddress.Length == 3)
- {
- char c1 = columnAddress[0];
- char c2 = columnAddress[1];
- char c3 = columnAddress[2];
- int i1 = c1 - 'A';
- int i2 = c2 - 'A';
- int i3 = c3 - 'A';
- return (i1 + 1) * 676 + (i2 + 1) * 26 + i3;
- }
- throw new FileFormatException("Invalid spreadsheet: Invalid column address.");
- }
- }
- }
|