/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs

# · C# · 1269 lines · 1050 code · 214 blank · 5 comment · 109 complexity · 51ca3382f82bfc8e1df4e23b98f2445b MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace ClosedXML.Excel
  5. {
  6. internal delegate void RangeShiftedRowsDelegate(XLRange range, Int32 rowsShifted);
  7. internal delegate void RangeShiftedColumnsDelegate(XLRange range, Int32 columnsShifted);
  8. internal class XLWorksheet : XLRangeBase, IXLWorksheet
  9. {
  10. #region Constants
  11. #endregion
  12. #region Events
  13. public event RangeShiftedRowsDelegate RangeShiftedRows;
  14. public event RangeShiftedColumnsDelegate RangeShiftedColumns;
  15. #endregion
  16. #region Fields
  17. private readonly Dictionary<Int32, Int32> _columnOutlineCount = new Dictionary<Int32, Int32>();
  18. private readonly Dictionary<Int32, Int32> _rowOutlineCount = new Dictionary<Int32, Int32>();
  19. internal Int32 ZOrder = 1;
  20. private String _name;
  21. internal Int32 _position;
  22. private Double _rowHeight;
  23. private Boolean _tabActive;
  24. internal readonly Boolean EventTrackingEnabled;
  25. #endregion
  26. #region Constructor
  27. public XLWorksheet(String sheetName, XLWorkbook workbook)
  28. : base(
  29. new XLRangeAddress(
  30. new XLAddress(null, ExcelHelper.MinRowNumber, ExcelHelper.MinColumnNumber, false, false),
  31. new XLAddress(null, ExcelHelper.MaxRowNumber, ExcelHelper.MaxColumnNumber, false, false)))
  32. {
  33. EventTrackingEnabled = workbook.EventTracking == XLEventTracking.Enabled;
  34. RangeAddress.Worksheet = this;
  35. RangeAddress.FirstAddress.Worksheet = this;
  36. RangeAddress.LastAddress.Worksheet = this;
  37. NamedRanges = new XLNamedRanges(workbook);
  38. SheetView = new XLSheetView();
  39. Tables = new XLTables();
  40. Hyperlinks = new XLHyperlinks();
  41. DataValidations = new XLDataValidations();
  42. PivotTables = new XLPivotTables();
  43. Protection = new XLSheetProtection();
  44. AutoFilter = new XLAutoFilter();
  45. Workbook = workbook;
  46. SetStyle(workbook.Style);
  47. Internals = new XLWorksheetInternals(new XLCellsCollection(), new XLColumnsCollection(),
  48. new XLRowsCollection(), new XLRanges());
  49. PageSetup = new XLPageSetup((XLPageSetup)workbook.PageOptions, this);
  50. Outline = new XLOutline(workbook.Outline);
  51. _columnWidth = workbook.ColumnWidth;
  52. _rowHeight = workbook.RowHeight;
  53. RowHeightChanged = Math.Abs(workbook.RowHeight - XLWorkbook.DefaultRowHeight) > ExcelHelper.Epsilon;
  54. Name = sheetName;
  55. SubscribeToShiftedRows(WorksheetRangeShiftedRows);
  56. SubscribeToShiftedColumns(WorksheetRangeShiftedColumns);
  57. Charts = new XLCharts();
  58. ShowFormulas = workbook.ShowFormulas;
  59. ShowGridLines = workbook.ShowGridLines;
  60. ShowOutlineSymbols = workbook.ShowOutlineSymbols;
  61. ShowRowColHeaders = workbook.ShowRowColHeaders;
  62. ShowRuler = workbook.ShowRuler;
  63. ShowWhiteSpace = workbook.ShowWhiteSpace;
  64. ShowZeros = workbook.ShowZeros;
  65. RightToLeft = workbook.RightToLeft;
  66. TabColor = new XLColor();
  67. }
  68. #endregion
  69. //private IXLStyle _style;
  70. private const String InvalidNameChars = @":\/?*[]";
  71. public string LegacyDrawingId;
  72. public Boolean LegacyDrawingIsNew;
  73. private Double _columnWidth;
  74. public XLWorksheetInternals Internals { get; private set; }
  75. public override IEnumerable<IXLStyle> Styles
  76. {
  77. get
  78. {
  79. UpdatingStyle = true;
  80. yield return GetStyle();
  81. foreach (XLCell c in Internals.CellsCollection.GetCells())
  82. yield return c.Style;
  83. UpdatingStyle = false;
  84. }
  85. }
  86. public override Boolean UpdatingStyle { get; set; }
  87. public override IXLStyle InnerStyle
  88. {
  89. get { return GetStyle(); }
  90. set { SetStyle(value); }
  91. }
  92. internal Boolean RowHeightChanged { get; set; }
  93. internal Boolean ColumnWidthChanged { get; set; }
  94. public Int32 SheetId { get; set; }
  95. public String RelId { get; set; }
  96. public XLDataValidations DataValidations { get; private set; }
  97. public IXLCharts Charts { get; private set; }
  98. public XLSheetProtection Protection { get; private set; }
  99. public XLAutoFilter AutoFilter { get; private set; }
  100. #region IXLWorksheet Members
  101. public XLWorkbook Workbook { get; private set; }
  102. public override IXLStyle Style
  103. {
  104. get { return GetStyle(); }
  105. set
  106. {
  107. SetStyle(value);
  108. foreach (XLCell cell in Internals.CellsCollection.GetCells())
  109. cell.Style = value;
  110. }
  111. }
  112. public Double ColumnWidth
  113. {
  114. get { return _columnWidth; }
  115. set
  116. {
  117. ColumnWidthChanged = true;
  118. _columnWidth = value;
  119. }
  120. }
  121. public Double RowHeight
  122. {
  123. get { return _rowHeight; }
  124. set
  125. {
  126. RowHeightChanged = true;
  127. _rowHeight = value;
  128. }
  129. }
  130. public String Name
  131. {
  132. get { return _name; }
  133. set
  134. {
  135. if (value.IndexOfAny(InvalidNameChars.ToCharArray()) != -1)
  136. throw new ArgumentException("Worksheet names cannot contain any of the following characters: " +
  137. InvalidNameChars);
  138. if (StringExtensions.IsNullOrWhiteSpace(value))
  139. throw new ArgumentException("Worksheet names cannot be empty");
  140. if (value.Length > 31)
  141. throw new ArgumentException("Worksheet names cannot be more than 31 characters");
  142. Workbook.WorksheetsInternal.Rename(_name, value);
  143. _name = value;
  144. }
  145. }
  146. public Int32 Position
  147. {
  148. get { return _position; }
  149. set
  150. {
  151. if (value > Workbook.WorksheetsInternal.Count + Workbook.UnsupportedSheets.Count + 1)
  152. throw new IndexOutOfRangeException("Index must be equal or less than the number of worksheets + 1.");
  153. if (value < _position)
  154. {
  155. Workbook.WorksheetsInternal
  156. .Where<XLWorksheet>(w => w.Position >= value && w.Position < _position)
  157. .ForEach(w => w._position += 1);
  158. }
  159. if (value > _position)
  160. {
  161. Workbook.WorksheetsInternal
  162. .Where<XLWorksheet>(w => w.Position <= value && w.Position > _position)
  163. .ForEach(w => (w)._position -= 1);
  164. }
  165. _position = value;
  166. }
  167. }
  168. public IXLPageSetup PageSetup { get; private set; }
  169. public IXLOutline Outline { get; private set; }
  170. IXLRow IXLWorksheet.FirstRowUsed()
  171. {
  172. return FirstRowUsed();
  173. }
  174. IXLRow IXLWorksheet.FirstRowUsed(Boolean includeFormats)
  175. {
  176. return FirstRowUsed(includeFormats);
  177. }
  178. IXLRow IXLWorksheet.LastRowUsed()
  179. {
  180. return LastRowUsed();
  181. }
  182. IXLRow IXLWorksheet.LastRowUsed(Boolean includeFormats)
  183. {
  184. return LastRowUsed(includeFormats);
  185. }
  186. IXLColumn IXLWorksheet.LastColumn()
  187. {
  188. return LastColumn();
  189. }
  190. IXLColumn IXLWorksheet.FirstColumn()
  191. {
  192. return FirstColumn();
  193. }
  194. IXLRow IXLWorksheet.FirstRow()
  195. {
  196. return FirstRow();
  197. }
  198. IXLRow IXLWorksheet.LastRow()
  199. {
  200. return LastRow();
  201. }
  202. IXLColumn IXLWorksheet.FirstColumnUsed()
  203. {
  204. return FirstColumnUsed();
  205. }
  206. IXLColumn IXLWorksheet.FirstColumnUsed(Boolean includeFormats)
  207. {
  208. return FirstColumnUsed(includeFormats);
  209. }
  210. IXLColumn IXLWorksheet.LastColumnUsed()
  211. {
  212. return LastColumnUsed();
  213. }
  214. IXLColumn IXLWorksheet.LastColumnUsed(Boolean includeFormats)
  215. {
  216. return LastColumnUsed(includeFormats);
  217. }
  218. public IXLColumns Columns()
  219. {
  220. var retVal = new XLColumns(this);
  221. var columnList = new List<Int32>();
  222. if (Internals.CellsCollection.Count > 0)
  223. columnList.AddRange(Internals.CellsCollection.ColumnsUsed.Keys);
  224. if (Internals.ColumnsCollection.Count > 0)
  225. columnList.AddRange(Internals.ColumnsCollection.Keys.Where(c => !columnList.Contains(c)));
  226. foreach (int c in columnList)
  227. retVal.Add(Column(c));
  228. return retVal;
  229. }
  230. public IXLColumns Columns(String columns)
  231. {
  232. var retVal = new XLColumns(null);
  233. var columnPairs = columns.Split(',');
  234. foreach (string tPair in columnPairs.Select(pair => pair.Trim()))
  235. {
  236. String firstColumn;
  237. String lastColumn;
  238. if (tPair.Contains(':') || tPair.Contains('-'))
  239. {
  240. var columnRange = ExcelHelper.SplitRange(tPair);
  241. firstColumn = columnRange[0];
  242. lastColumn = columnRange[1];
  243. }
  244. else
  245. {
  246. firstColumn = tPair;
  247. lastColumn = tPair;
  248. }
  249. Int32 tmp;
  250. if (Int32.TryParse(firstColumn, out tmp))
  251. {
  252. foreach (IXLColumn col in Columns(Int32.Parse(firstColumn), Int32.Parse(lastColumn)))
  253. retVal.Add((XLColumn)col);
  254. }
  255. else
  256. {
  257. foreach (IXLColumn col in Columns(firstColumn, lastColumn))
  258. retVal.Add((XLColumn)col);
  259. }
  260. }
  261. return retVal;
  262. }
  263. public IXLColumns Columns(String firstColumn, String lastColumn)
  264. {
  265. return Columns(ExcelHelper.GetColumnNumberFromLetter(firstColumn),
  266. ExcelHelper.GetColumnNumberFromLetter(lastColumn));
  267. }
  268. public IXLColumns Columns(Int32 firstColumn, Int32 lastColumn)
  269. {
  270. var retVal = new XLColumns(null);
  271. for (int co = firstColumn; co <= lastColumn; co++)
  272. retVal.Add(Column(co));
  273. return retVal;
  274. }
  275. public IXLRows Rows()
  276. {
  277. var retVal = new XLRows(this);
  278. var rowList = new List<Int32>();
  279. if (Internals.CellsCollection.Count > 0)
  280. rowList.AddRange(Internals.CellsCollection.RowsUsed.Keys);
  281. if (Internals.RowsCollection.Count > 0)
  282. rowList.AddRange(Internals.RowsCollection.Keys.Where(r => !rowList.Contains(r)));
  283. foreach (int r in rowList)
  284. retVal.Add(Row(r));
  285. return retVal;
  286. }
  287. public IXLRows Rows(String rows)
  288. {
  289. var retVal = new XLRows(null);
  290. var rowPairs = rows.Split(',');
  291. foreach (string tPair in rowPairs.Select(pair => pair.Trim()))
  292. {
  293. String firstRow;
  294. String lastRow;
  295. if (tPair.Contains(':') || tPair.Contains('-'))
  296. {
  297. var rowRange = ExcelHelper.SplitRange(tPair);
  298. firstRow = rowRange[0];
  299. lastRow = rowRange[1];
  300. }
  301. else
  302. {
  303. firstRow = tPair;
  304. lastRow = tPair;
  305. }
  306. foreach (IXLRow row in Rows(Int32.Parse(firstRow), Int32.Parse(lastRow)))
  307. retVal.Add((XLRow)row);
  308. }
  309. return retVal;
  310. }
  311. public IXLRows Rows(Int32 firstRow, Int32 lastRow)
  312. {
  313. var retVal = new XLRows(null);
  314. for (int ro = firstRow; ro <= lastRow; ro++)
  315. retVal.Add(Row(ro));
  316. return retVal;
  317. }
  318. IXLRow IXLWorksheet.Row(Int32 row)
  319. {
  320. return Row(row);
  321. }
  322. IXLColumn IXLWorksheet.Column(Int32 column)
  323. {
  324. return Column(column);
  325. }
  326. IXLColumn IXLWorksheet.Column(String column)
  327. {
  328. return Column(column);
  329. }
  330. IXLCell IXLWorksheet.Cell(int row, int column)
  331. {
  332. return Cell(row, column);
  333. }
  334. IXLCell IXLWorksheet.Cell(string cellAddressInRange)
  335. {
  336. return Cell(cellAddressInRange);
  337. }
  338. IXLCell IXLWorksheet.Cell(int row, string column)
  339. {
  340. return Cell(row, column);
  341. }
  342. IXLCell IXLWorksheet.Cell(IXLAddress cellAddressInRange)
  343. {
  344. return Cell(cellAddressInRange);
  345. }
  346. IXLRange IXLWorksheet.Range(IXLRangeAddress rangeAddress)
  347. {
  348. return Range(rangeAddress);
  349. }
  350. IXLRange IXLWorksheet.Range(string rangeAddress)
  351. {
  352. return Range(rangeAddress);
  353. }
  354. IXLRange IXLWorksheet.Range(IXLCell firstCell, IXLCell lastCell)
  355. {
  356. return Range(firstCell, lastCell);
  357. }
  358. IXLRange IXLWorksheet.Range(string firstCellAddress, string lastCellAddress)
  359. {
  360. return Range(firstCellAddress, lastCellAddress);
  361. }
  362. IXLRange IXLWorksheet.Range(IXLAddress firstCellAddress, IXLAddress lastCellAddress)
  363. {
  364. return Range(firstCellAddress, lastCellAddress);
  365. }
  366. IXLRange IXLWorksheet.Range(int firstCellRow, int firstCellColumn, int lastCellRow, int lastCellColumn)
  367. {
  368. return Range(firstCellRow, firstCellColumn, lastCellRow, lastCellColumn);
  369. }
  370. public IXLWorksheet CollapseRows()
  371. {
  372. Enumerable.Range(1, 8).ForEach(i => CollapseRows(i));
  373. return this;
  374. }
  375. public IXLWorksheet CollapseColumns()
  376. {
  377. Enumerable.Range(1, 8).ForEach(i => CollapseColumns(i));
  378. return this;
  379. }
  380. public IXLWorksheet ExpandRows()
  381. {
  382. Enumerable.Range(1, 8).ForEach(i => ExpandRows(i));
  383. return this;
  384. }
  385. public IXLWorksheet ExpandColumns()
  386. {
  387. Enumerable.Range(1, 8).ForEach(i => ExpandRows(i));
  388. return this;
  389. }
  390. public IXLWorksheet CollapseRows(Int32 outlineLevel)
  391. {
  392. if (outlineLevel < 1 || outlineLevel > 8)
  393. throw new ArgumentOutOfRangeException("outlineLevel", "Outline level must be between 1 and 8.");
  394. Internals.RowsCollection.Values.Where(r => r.OutlineLevel == outlineLevel).ForEach(r => r.Collapse());
  395. return this;
  396. }
  397. public IXLWorksheet CollapseColumns(Int32 outlineLevel)
  398. {
  399. if (outlineLevel < 1 || outlineLevel > 8)
  400. throw new ArgumentOutOfRangeException("outlineLevel", "Outline level must be between 1 and 8.");
  401. Internals.ColumnsCollection.Values.Where(c => c.OutlineLevel == outlineLevel).ForEach(c => c.Collapse());
  402. return this;
  403. }
  404. public IXLWorksheet ExpandRows(Int32 outlineLevel)
  405. {
  406. if (outlineLevel < 1 || outlineLevel > 8)
  407. throw new ArgumentOutOfRangeException("outlineLevel", "Outline level must be between 1 and 8.");
  408. Internals.RowsCollection.Values.Where(r => r.OutlineLevel == outlineLevel).ForEach(r => r.Expand());
  409. return this;
  410. }
  411. public IXLWorksheet ExpandColumns(Int32 outlineLevel)
  412. {
  413. if (outlineLevel < 1 || outlineLevel > 8)
  414. throw new ArgumentOutOfRangeException("outlineLevel", "Outline level must be between 1 and 8.");
  415. Internals.ColumnsCollection.Values.Where(c => c.OutlineLevel == outlineLevel).ForEach(c => c.Expand());
  416. return this;
  417. }
  418. public void Delete()
  419. {
  420. Workbook.WorksheetsInternal.Delete(Name);
  421. }
  422. public IXLNamedRanges NamedRanges { get; private set; }
  423. public IXLNamedRange NamedRange(String rangeName)
  424. {
  425. return NamedRanges.NamedRange(rangeName);
  426. }
  427. public IXLSheetView SheetView { get; private set; }
  428. public IXLTables Tables { get; private set; }
  429. public IXLTable Table(Int32 index)
  430. {
  431. return Tables.Table(index);
  432. }
  433. public IXLTable Table(String name)
  434. {
  435. return Tables.Table(name);
  436. }
  437. public IXLWorksheet CopyTo(String newSheetName)
  438. {
  439. return CopyTo(Workbook, newSheetName, Workbook.WorksheetsInternal.Count + 1);
  440. }
  441. public IXLWorksheet CopyTo(String newSheetName, Int32 position)
  442. {
  443. return CopyTo(Workbook, newSheetName, position);
  444. }
  445. public IXLWorksheet CopyTo(XLWorkbook workbook, String newSheetName)
  446. {
  447. return CopyTo(workbook, newSheetName, workbook.WorksheetsInternal.Count + 1);
  448. }
  449. public IXLWorksheet CopyTo(XLWorkbook workbook, String newSheetName, Int32 position)
  450. {
  451. var targetSheet = (XLWorksheet)workbook.WorksheetsInternal.Add(newSheetName, position);
  452. Internals.CellsCollection.GetCells().ForEach(c => targetSheet.Cell(c.Address).CopyFrom(c, false));
  453. DataValidations.ForEach(dv => targetSheet.DataValidations.Add(new XLDataValidation(dv)));
  454. Internals.ColumnsCollection.ForEach(
  455. kp => targetSheet.Internals.ColumnsCollection.Add(kp.Key, new XLColumn(kp.Value)));
  456. Internals.RowsCollection.ForEach(kp => targetSheet.Internals.RowsCollection.Add(kp.Key, new XLRow(kp.Value)));
  457. targetSheet.Visibility = Visibility;
  458. targetSheet.ColumnWidth = ColumnWidth;
  459. targetSheet.ColumnWidthChanged = ColumnWidthChanged;
  460. targetSheet.RowHeight = RowHeight;
  461. targetSheet.RowHeightChanged = RowHeightChanged;
  462. targetSheet.SetStyle(Style);
  463. targetSheet.PageSetup = new XLPageSetup((XLPageSetup)PageSetup, targetSheet);
  464. targetSheet.Outline = new XLOutline(Outline);
  465. targetSheet.SheetView = new XLSheetView(SheetView);
  466. Internals.MergedRanges.ForEach(
  467. kp => targetSheet.Internals.MergedRanges.Add(targetSheet.Range(kp.RangeAddress.ToString())));
  468. foreach (IXLNamedRange r in NamedRanges)
  469. {
  470. var ranges = new XLRanges();
  471. r.Ranges.ForEach(ranges.Add);
  472. targetSheet.NamedRanges.Add(r.Name, ranges);
  473. }
  474. foreach (XLTable t in Tables.Cast<XLTable>())
  475. {
  476. String tableName = t.Name;
  477. var table = targetSheet.Tables.Any(tt => tt.Name == tableName)
  478. ? new XLTable(targetSheet.Range(t.RangeAddress.ToString()), true)
  479. : new XLTable(targetSheet.Range(t.RangeAddress.ToString()), tableName, true);
  480. table.RelId = t.RelId;
  481. table.EmphasizeFirstColumn = t.EmphasizeFirstColumn;
  482. table.EmphasizeLastColumn = t.EmphasizeLastColumn;
  483. table.ShowRowStripes = t.ShowRowStripes;
  484. table.ShowColumnStripes = t.ShowColumnStripes;
  485. table.ShowAutoFilter = t.ShowAutoFilter;
  486. table.Theme = t.Theme;
  487. table._showTotalsRow = t.ShowTotalsRow;
  488. table._uniqueNames.Clear();
  489. t._uniqueNames.ForEach(n => table._uniqueNames.Add(n));
  490. Int32 fieldCount = t.ColumnCount();
  491. for (Int32 f = 0; f < fieldCount; f++)
  492. {
  493. table.Field(f).Index = t.Field(f).Index;
  494. table.Field(f).Name = t.Field(f).Name;
  495. (table.Field(f) as XLTableField).totalsRowLabel = (t.Field(f) as XLTableField).totalsRowLabel;
  496. (table.Field(f) as XLTableField).totalsRowFunction = (t.Field(f) as XLTableField).totalsRowFunction;
  497. }
  498. }
  499. if (AutoFilter.Enabled)
  500. targetSheet.Range(AutoFilter.Range.RangeAddress).SetAutoFilter();
  501. return targetSheet;
  502. }
  503. public new IXLHyperlinks Hyperlinks { get; private set; }
  504. IXLDataValidations IXLWorksheet.DataValidations
  505. {
  506. get { return DataValidations; }
  507. }
  508. public XLWorksheetVisibility Visibility { get; set; }
  509. public IXLWorksheet Hide()
  510. {
  511. Visibility = XLWorksheetVisibility.Hidden;
  512. return this;
  513. }
  514. public IXLWorksheet Unhide()
  515. {
  516. Visibility = XLWorksheetVisibility.Visible;
  517. return this;
  518. }
  519. IXLSheetProtection IXLWorksheet.Protection
  520. {
  521. get { return Protection; }
  522. }
  523. public IXLSheetProtection Protect()
  524. {
  525. return Protection.Protect();
  526. }
  527. public IXLSheetProtection Protect(String password)
  528. {
  529. return Protection.Protect(password);
  530. }
  531. public IXLSheetProtection Unprotect()
  532. {
  533. return Protection.Unprotect();
  534. }
  535. public IXLSheetProtection Unprotect(String password)
  536. {
  537. return Protection.Unprotect(password);
  538. }
  539. public new IXLRange Sort()
  540. {
  541. return GetRangeForSort().Sort();
  542. }
  543. public new IXLRange Sort(String columnsToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending,
  544. Boolean matchCase = false, Boolean ignoreBlanks = true)
  545. {
  546. return GetRangeForSort().Sort(columnsToSortBy, sortOrder, matchCase, ignoreBlanks);
  547. }
  548. public new IXLRange Sort(Int32 columnToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending,
  549. Boolean matchCase = false, Boolean ignoreBlanks = true)
  550. {
  551. return GetRangeForSort().Sort(columnToSortBy, sortOrder, matchCase, ignoreBlanks);
  552. }
  553. public new IXLRange SortLeftToRight(XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false,
  554. Boolean ignoreBlanks = true)
  555. {
  556. return GetRangeForSort().SortLeftToRight(sortOrder, matchCase, ignoreBlanks);
  557. }
  558. public Boolean ShowFormulas { get; set; }
  559. public Boolean ShowGridLines { get; set; }
  560. public Boolean ShowOutlineSymbols { get; set; }
  561. public Boolean ShowRowColHeaders { get; set; }
  562. public Boolean ShowRuler { get; set; }
  563. public Boolean ShowWhiteSpace { get; set; }
  564. public Boolean ShowZeros { get; set; }
  565. public IXLWorksheet SetShowFormulas()
  566. {
  567. ShowFormulas = true;
  568. return this;
  569. }
  570. public IXLWorksheet SetShowFormulas(Boolean value)
  571. {
  572. ShowFormulas = value;
  573. return this;
  574. }
  575. public IXLWorksheet SetShowGridLines()
  576. {
  577. ShowGridLines = true;
  578. return this;
  579. }
  580. public IXLWorksheet SetShowGridLines(Boolean value)
  581. {
  582. ShowGridLines = value;
  583. return this;
  584. }
  585. public IXLWorksheet SetShowOutlineSymbols()
  586. {
  587. ShowOutlineSymbols = true;
  588. return this;
  589. }
  590. public IXLWorksheet SetShowOutlineSymbols(Boolean value)
  591. {
  592. ShowOutlineSymbols = value;
  593. return this;
  594. }
  595. public IXLWorksheet SetShowRowColHeaders()
  596. {
  597. ShowRowColHeaders = true;
  598. return this;
  599. }
  600. public IXLWorksheet SetShowRowColHeaders(Boolean value)
  601. {
  602. ShowRowColHeaders = value;
  603. return this;
  604. }
  605. public IXLWorksheet SetShowRuler()
  606. {
  607. ShowRuler = true;
  608. return this;
  609. }
  610. public IXLWorksheet SetShowRuler(Boolean value)
  611. {
  612. ShowRuler = value;
  613. return this;
  614. }
  615. public IXLWorksheet SetShowWhiteSpace()
  616. {
  617. ShowWhiteSpace = true;
  618. return this;
  619. }
  620. public IXLWorksheet SetShowWhiteSpace(Boolean value)
  621. {
  622. ShowWhiteSpace = value;
  623. return this;
  624. }
  625. public IXLWorksheet SetShowZeros()
  626. {
  627. ShowZeros = true;
  628. return this;
  629. }
  630. public IXLWorksheet SetShowZeros(Boolean value)
  631. {
  632. ShowZeros = value;
  633. return this;
  634. }
  635. public IXLColor TabColor { get; set; }
  636. public IXLWorksheet SetTabColor(IXLColor color)
  637. {
  638. TabColor = color;
  639. return this;
  640. }
  641. public Boolean TabSelected { get; set; }
  642. public Boolean TabActive
  643. {
  644. get { return _tabActive; }
  645. set
  646. {
  647. if (value && !_tabActive)
  648. {
  649. foreach (XLWorksheet ws in Worksheet.Workbook.WorksheetsInternal)
  650. ws._tabActive = false;
  651. }
  652. _tabActive = value;
  653. }
  654. }
  655. public IXLWorksheet SetTabSelected()
  656. {
  657. TabSelected = true;
  658. return this;
  659. }
  660. public IXLWorksheet SetTabSelected(Boolean value)
  661. {
  662. TabSelected = value;
  663. return this;
  664. }
  665. public IXLWorksheet SetTabActive()
  666. {
  667. TabActive = true;
  668. return this;
  669. }
  670. public IXLWorksheet SetTabActive(Boolean value)
  671. {
  672. TabActive = value;
  673. return this;
  674. }
  675. IXLPivotTable IXLWorksheet.PivotTable(String name)
  676. {
  677. return PivotTable(name);
  678. }
  679. public IXLPivotTables PivotTables { get; private set; }
  680. public Boolean RightToLeft { get; set; }
  681. public IXLWorksheet SetRightToLeft()
  682. {
  683. RightToLeft = true;
  684. return this;
  685. }
  686. public IXLWorksheet SetRightToLeft(Boolean value)
  687. {
  688. RightToLeft = value;
  689. return this;
  690. }
  691. public new IXLRanges Ranges(String ranges)
  692. {
  693. var retVal = new XLRanges();
  694. foreach (string rangeAddressStr in ranges.Split(',').Select(s => s.Trim()))
  695. {
  696. if (ExcelHelper.IsValidRangeAddress(rangeAddressStr))
  697. retVal.Add(Range(new XLRangeAddress(Worksheet, rangeAddressStr)));
  698. else if (NamedRanges.Any(n => String.Compare(n.Name, rangeAddressStr, true) == 0))
  699. NamedRange(rangeAddressStr).Ranges.ForEach(retVal.Add);
  700. else
  701. {
  702. Workbook.NamedRanges.First(n =>
  703. String.Compare(n.Name, rangeAddressStr, true) == 0
  704. && n.Ranges.First().Worksheet == this)
  705. .Ranges.ForEach(retVal.Add);
  706. }
  707. }
  708. return retVal;
  709. }
  710. IXLBaseAutoFilter IXLWorksheet.AutoFilter
  711. {
  712. get { return AutoFilter; }
  713. }
  714. public IXLRows RowsUsed(Boolean includeFormats = false, Func<IXLRow, Boolean> predicate = null)
  715. {
  716. var rows = new XLRows(Worksheet);
  717. var rowsUsed = new HashSet<Int32>();
  718. Internals.RowsCollection.Keys.ForEach(r => rowsUsed.Add(r));
  719. Internals.CellsCollection.RowsUsed.Keys.ForEach(r => rowsUsed.Add(r));
  720. foreach (var rowNum in rowsUsed)
  721. {
  722. var row = Row(rowNum);
  723. if (!row.IsEmpty(includeFormats) && (predicate == null || predicate(row)))
  724. rows.Add(row);
  725. else
  726. row.Dispose();
  727. }
  728. return rows;
  729. }
  730. public IXLRows RowsUsed(Func<IXLRow, Boolean> predicate = null)
  731. {
  732. return RowsUsed(false, predicate);
  733. }
  734. public IXLColumns ColumnsUsed(Boolean includeFormats = false, Func<IXLColumn, Boolean> predicate = null)
  735. {
  736. var columns = new XLColumns(Worksheet);
  737. var columnsUsed = new HashSet<Int32>();
  738. Internals.ColumnsCollection.Keys.ForEach(r => columnsUsed.Add(r));
  739. Internals.CellsCollection.ColumnsUsed.Keys.ForEach(r => columnsUsed.Add(r));
  740. foreach (var columnNum in columnsUsed)
  741. {
  742. var column = Column(columnNum);
  743. if (!column.IsEmpty(includeFormats) && (predicate == null || predicate(column)))
  744. columns.Add(column);
  745. else
  746. column.Dispose();
  747. }
  748. return columns;
  749. }
  750. public IXLColumns ColumnsUsed(Func<IXLColumn, Boolean> predicate = null)
  751. {
  752. return ColumnsUsed(false, predicate);
  753. }
  754. public new void Dispose()
  755. {
  756. if (AutoFilter != null)
  757. AutoFilter.Dispose();
  758. Internals.Dispose();
  759. base.Dispose();
  760. }
  761. #endregion
  762. #region Outlines
  763. public void IncrementColumnOutline(Int32 level)
  764. {
  765. if (level <= 0) return;
  766. if (!_columnOutlineCount.ContainsKey(level))
  767. _columnOutlineCount.Add(level, 0);
  768. _columnOutlineCount[level]++;
  769. }
  770. public void DecrementColumnOutline(Int32 level)
  771. {
  772. if (level <= 0) return;
  773. if (!_columnOutlineCount.ContainsKey(level))
  774. _columnOutlineCount.Add(level, 0);
  775. if (_columnOutlineCount[level] > 0)
  776. _columnOutlineCount[level]--;
  777. }
  778. public Int32 GetMaxColumnOutline()
  779. {
  780. return _columnOutlineCount.Count == 0 ? 0 : _columnOutlineCount.Where(kp => kp.Value > 0).Max(kp => kp.Key);
  781. }
  782. public void IncrementRowOutline(Int32 level)
  783. {
  784. if (level <= 0) return;
  785. if (!_rowOutlineCount.ContainsKey(level))
  786. _rowOutlineCount.Add(level, 0);
  787. _rowOutlineCount[level]++;
  788. }
  789. public void DecrementRowOutline(Int32 level)
  790. {
  791. if (level <= 0) return;
  792. if (!_rowOutlineCount.ContainsKey(level))
  793. _rowOutlineCount.Add(level, 0);
  794. if (_rowOutlineCount[level] > 0)
  795. _rowOutlineCount[level]--;
  796. }
  797. public Int32 GetMaxRowOutline()
  798. {
  799. return _rowOutlineCount.Count == 0 ? 0 : _rowOutlineCount.Where(kp => kp.Value > 0).Max(kp => kp.Key);
  800. }
  801. #endregion
  802. public HashSet<Int32> GetStyleIds()
  803. {
  804. var retVal = new HashSet<Int32> {GetStyleId()};
  805. foreach (
  806. int id in
  807. Internals.CellsCollection.GetCells().Select(c => c.GetStyleId()).Where(id => !retVal.Contains(id)))
  808. retVal.Add(id);
  809. return retVal;
  810. }
  811. public XLRow FirstRowUsed()
  812. {
  813. return FirstRowUsed(false);
  814. }
  815. public XLRow FirstRowUsed(Boolean includeFormats)
  816. {
  817. using (var asRange = AsRange())
  818. using (var rngRow = asRange.FirstRowUsed(includeFormats))
  819. return rngRow != null ? Row(rngRow.RangeAddress.FirstAddress.RowNumber) : null;
  820. }
  821. public XLRow LastRowUsed()
  822. {
  823. return LastRowUsed(false);
  824. }
  825. public XLRow LastRowUsed(Boolean includeFormats)
  826. {
  827. using (var asRange = AsRange())
  828. using (var rngRow = asRange.LastRowUsed(includeFormats))
  829. return rngRow != null ? Row(rngRow.RangeAddress.LastAddress.RowNumber) : null;
  830. }
  831. public XLColumn LastColumn()
  832. {
  833. return Column(ExcelHelper.MaxColumnNumber);
  834. }
  835. public XLColumn FirstColumn()
  836. {
  837. return Column(1);
  838. }
  839. public XLRow FirstRow()
  840. {
  841. return Row(1);
  842. }
  843. public XLRow LastRow()
  844. {
  845. return Row(ExcelHelper.MaxRowNumber);
  846. }
  847. public XLColumn FirstColumnUsed()
  848. {
  849. return FirstColumnUsed(false);
  850. }
  851. public XLColumn FirstColumnUsed(Boolean includeFormats)
  852. {
  853. using (var asRange = AsRange())
  854. using (var rngColumn = asRange.FirstColumnUsed(includeFormats))
  855. return rngColumn != null ? Column(rngColumn.RangeAddress.FirstAddress.ColumnNumber) : null;
  856. }
  857. public XLColumn LastColumnUsed()
  858. {
  859. return LastColumnUsed(false);
  860. }
  861. public XLColumn LastColumnUsed(Boolean includeFormats)
  862. {
  863. using (var asRange = AsRange())
  864. using (var rngColumn = asRange.LastColumnUsed(includeFormats))
  865. return rngColumn != null ? Column(rngColumn.RangeAddress.LastAddress.ColumnNumber) : null;
  866. }
  867. public XLRow Row(Int32 row)
  868. {
  869. return Row(row, true);
  870. }
  871. public XLColumn Column(Int32 column)
  872. {
  873. if (column <= 0 || column > ExcelHelper.MaxColumnNumber)
  874. throw new IndexOutOfRangeException(String.Format("Column number must be between 1 and {0}",
  875. ExcelHelper.MaxColumnNumber));
  876. Int32 thisStyleId = GetStyleId();
  877. if (!Internals.ColumnsCollection.ContainsKey(column))
  878. {
  879. // This is a new row so we're going to reference all
  880. // cells in this row to preserve their formatting
  881. Internals.RowsCollection.Keys.ForEach(r => Cell(r, column));
  882. Internals.ColumnsCollection.Add(column,
  883. new XLColumn(column, new XLColumnParameters(this, thisStyleId, false)));
  884. }
  885. return new XLColumn(column, new XLColumnParameters(this, thisStyleId, true));
  886. }
  887. public IXLColumn Column(String column)
  888. {
  889. return Column(ExcelHelper.GetColumnNumberFromLetter(column));
  890. }
  891. public override XLRange AsRange()
  892. {
  893. return Range(1, 1, ExcelHelper.MaxRowNumber, ExcelHelper.MaxColumnNumber);
  894. }
  895. public void Clear()
  896. {
  897. Internals.CellsCollection.Clear();
  898. Internals.ColumnsCollection.Clear();
  899. Internals.MergedRanges.Clear();
  900. Internals.RowsCollection.Clear();
  901. }
  902. private void WorksheetRangeShiftedColumns(XLRange range, int columnsShifted)
  903. {
  904. var newMerge = new XLRanges();
  905. foreach (IXLRange rngMerged in Internals.MergedRanges)
  906. {
  907. if (range.RangeAddress.FirstAddress.ColumnNumber <= rngMerged.RangeAddress.FirstAddress.ColumnNumber
  908. && rngMerged.RangeAddress.FirstAddress.RowNumber >= range.RangeAddress.FirstAddress.RowNumber
  909. && rngMerged.RangeAddress.LastAddress.RowNumber <= range.RangeAddress.LastAddress.RowNumber)
  910. {
  911. var newRng = Range(
  912. rngMerged.RangeAddress.FirstAddress.RowNumber,
  913. rngMerged.RangeAddress.FirstAddress.ColumnNumber + columnsShifted,
  914. rngMerged.RangeAddress.LastAddress.RowNumber,
  915. rngMerged.RangeAddress.LastAddress.ColumnNumber + columnsShifted);
  916. newMerge.Add(newRng);
  917. }
  918. else if (
  919. !(range.RangeAddress.FirstAddress.ColumnNumber <= rngMerged.RangeAddress.FirstAddress.ColumnNumber
  920. && range.RangeAddress.FirstAddress.RowNumber <= rngMerged.RangeAddress.LastAddress.RowNumber))
  921. newMerge.Add(rngMerged);
  922. }
  923. Internals.MergedRanges = newMerge;
  924. Workbook.Worksheets.ForEach(ws => MoveNamedRangesColumns(range, columnsShifted, ws.NamedRanges));
  925. MoveNamedRangesColumns(range, columnsShifted, Workbook.NamedRanges);
  926. }
  927. private void WorksheetRangeShiftedRows(XLRange range, int rowsShifted)
  928. {
  929. var newMerge = new XLRanges();
  930. foreach (IXLRange rngMerged in Internals.MergedRanges)
  931. {
  932. if (range.RangeAddress.FirstAddress.RowNumber <= rngMerged.RangeAddress.FirstAddress.RowNumber
  933. && rngMerged.RangeAddress.FirstAddress.ColumnNumber >= range.RangeAddress.FirstAddress.ColumnNumber
  934. && rngMerged.RangeAddress.LastAddress.ColumnNumber <= range.RangeAddress.LastAddress.ColumnNumber)
  935. {
  936. var newRng = Range(
  937. rngMerged.RangeAddress.FirstAddress.RowNumber + rowsShifted,
  938. rngMerged.RangeAddress.FirstAddress.ColumnNumber,
  939. rngMerged.RangeAddress.LastAddress.RowNumber + rowsShifted,
  940. rngMerged.RangeAddress.LastAddress.ColumnNumber);
  941. newMerge.Add(newRng);
  942. }
  943. else if (!(range.RangeAddress.FirstAddress.RowNumber <= rngMerged.RangeAddress.FirstAddress.RowNumber
  944. &&
  945. range.RangeAddress.FirstAddress.ColumnNumber <=
  946. rngMerged.RangeAddress.LastAddress.ColumnNumber))
  947. newMerge.Add(rngMerged);
  948. }
  949. Internals.MergedRanges = newMerge;
  950. Workbook.Worksheets.ForEach(ws => MoveNamedRangesRows(range, rowsShifted, ws.NamedRanges));
  951. MoveNamedRangesRows(range, rowsShifted, Workbook.NamedRanges);
  952. }
  953. private void MoveNamedRangesRows(XLRange range, int rowsShifted, IXLNamedRanges namedRanges)
  954. {
  955. foreach (XLNamedRange nr in namedRanges)
  956. {
  957. var newRangeList =
  958. nr.RangeList.Select(r => XLCell.ShiftFormulaRows(r, this, range, rowsShifted)).Where(
  959. newReference => newReference.Length > 0).ToList();
  960. nr.RangeList = newRangeList;
  961. }
  962. }
  963. private void MoveNamedRangesColumns(XLRange range, int columnsShifted, IXLNamedRanges namedRanges)
  964. {
  965. foreach (XLNamedRange nr in namedRanges)
  966. {
  967. var newRangeList =
  968. nr.RangeList.Select(r => XLCell.ShiftFormulaColumns(r, this, range, columnsShifted)).Where(
  969. newReference => newReference.Length > 0).ToList();
  970. nr.RangeList = newRangeList;
  971. }
  972. }
  973. public void NotifyRangeShiftedRows(XLRange range, Int32 rowsShifted)
  974. {
  975. if (RangeShiftedRows != null)
  976. RangeShiftedRows(range, rowsShifted);
  977. }
  978. public void NotifyRangeShiftedColumns(XLRange range, Int32 columnsShifted)
  979. {
  980. if (RangeShiftedColumns != null)
  981. RangeShiftedColumns(range, columnsShifted);
  982. }
  983. public XLRow Row(Int32 row, Boolean pingCells)
  984. {
  985. if (row <= 0 || row > ExcelHelper.MaxRowNumber)
  986. throw new IndexOutOfRangeException(String.Format("Row number must be between 1 and {0}",
  987. ExcelHelper.MaxRowNumber));
  988. Int32 styleId;
  989. XLRow rowToUse;
  990. if (Internals.RowsCollection.TryGetValue(row, out rowToUse))
  991. styleId = rowToUse.GetStyleId();
  992. else
  993. {
  994. if (pingCells)
  995. {
  996. // This is a new row so we're going to reference all
  997. // cells in columns of this row to preserve their formatting
  998. var usedColumns = from c in Internals.ColumnsCollection
  999. join dc in Internals.CellsCollection.ColumnsUsed.Keys
  1000. on c.Key equals dc
  1001. where !Internals.CellsCollection.Contains(row, dc)
  1002. select dc;
  1003. usedColumns.ForEach(c => Cell(row, c));
  1004. }
  1005. styleId = GetStyleId();
  1006. Internals.RowsCollection.Add(row, new XLRow(row, new XLRowParameters(this, styleId, false)));
  1007. }
  1008. return new XLRow(row, new XLRowParameters(this, styleId));
  1009. }
  1010. private IXLRange GetRangeForSort()
  1011. {
  1012. var range = RangeUsed();
  1013. SortColumns.ForEach(e => range.SortColumns.Add(e.ElementNumber, e.SortOrder, e.IgnoreBlanks, e.MatchCase));
  1014. SortRows.ForEach(e => range.SortRows.Add(e.ElementNumber, e.SortOrder, e.IgnoreBlanks, e.MatchCase));
  1015. return range;
  1016. }
  1017. public XLPivotTable PivotTable(String name)
  1018. {
  1019. return (XLPivotTable)PivotTables.PivotTable(name);
  1020. }
  1021. public new XLCells Cells()
  1022. {
  1023. return CellsUsed(true);
  1024. }
  1025. public new XLCell Cell(String cellAddressInRange)
  1026. {
  1027. if (ExcelHelper.IsValidA1Address(cellAddressInRange))
  1028. return Cell(XLAddress.Create(this, cellAddressInRange));
  1029. if (NamedRanges.Any(n => String.Compare(n.Name, cellAddressInRange, true) == 0))
  1030. return (XLCell)NamedRange(cellAddressInRange).Ranges.First().FirstCell();
  1031. return (XLCell)Workbook.NamedRanges.First(n =>
  1032. String.Compare(n.Name, cellAddressInRange, true) == 0
  1033. && n.Ranges.First().Worksheet == this
  1034. && n.Ranges.Count == 1)
  1035. .Ranges.First().FirstCell();
  1036. }
  1037. public XLCell CellFast(String cellAddressInRange)
  1038. {
  1039. return Cell(XLAddress.Create(this, cellAddressInRange));
  1040. }
  1041. public override XLRange Range(String rangeAddressStr)
  1042. {
  1043. if (ExcelHelper.IsValidRangeAddress(rangeAddressStr))
  1044. return Range(new XLRangeAddress(Worksheet, rangeAddressStr));
  1045. if (NamedRanges.Any(n => String.Compare(n.Name, rangeAddressStr, true) == 0))
  1046. return (XLRange)NamedRange(rangeAddressStr).Ranges.First();
  1047. return (XLRange)Workbook.NamedRanges.First(n =>
  1048. String.Compare(n.Name, rangeAddressStr, true) == 0
  1049. && n.Ranges.First().Worksheet == this
  1050. && n.Ranges.Count == 1)
  1051. .Ranges.First();
  1052. }
  1053. public IXLRanges MergedRanges { get { return Internals.MergedRanges; } }
  1054. }
  1055. }