NPOISpreadsheet.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Xml.Linq;
  6. using InABox.Core;
  7. using NPOI.SS.Formula.Functions;
  8. using NPOI.SS.UserModel;
  9. using NPOI.XSSF.UserModel;
  10. using NCell = NPOI.SS.UserModel.ICell;
  11. using NRow = NPOI.SS.UserModel.IRow;
  12. using NSheet = NPOI.SS.UserModel.ISheet;
  13. using NDataFormat = NPOI.SS.UserModel.IDataFormat;
  14. using NCellStyle = NPOI.SS.UserModel.ICellStyle;
  15. using NPOI.SS.Util;
  16. namespace InABox.Scripting
  17. {
  18. public class RowEnumerator : IEnumerator<Row>
  19. {
  20. private IEnumerator _enumerator { get; set; }
  21. public Row Current => new Row(_enumerator.Current as NRow);
  22. object IEnumerator.Current => new Row(_enumerator.Current as NRow);
  23. internal RowEnumerator(IEnumerator enumerator)
  24. {
  25. _enumerator = enumerator;
  26. }
  27. public bool MoveNext()
  28. {
  29. return _enumerator.MoveNext();
  30. }
  31. public void Reset()
  32. {
  33. _enumerator.Reset();
  34. }
  35. public void Dispose()
  36. {
  37. }
  38. }
  39. public class Sheet : ISheet
  40. {
  41. private NSheet _sheet;
  42. public string Name => _sheet.SheetName;
  43. internal Sheet(NSheet sheet)
  44. {
  45. _sheet = sheet;
  46. }
  47. public IEnumerable<IRow> Rows()
  48. {
  49. var enumerator = _sheet.GetRowEnumerator();
  50. var row = 0;
  51. while (enumerator.MoveNext() && row <= int.MaxValue)
  52. {
  53. yield return new Row((NRow)enumerator.Current);
  54. row++;
  55. }
  56. }
  57. public IEnumerator<IRow> RowEnumerator()
  58. {
  59. return new RowEnumerator(_sheet.GetRowEnumerator());
  60. }
  61. public IRow NewRow()
  62. {
  63. var row = _sheet.CreateRow(_sheet.LastRowNum + 1);
  64. return new Row(row);
  65. }
  66. public ISheet SetColumnWidth(int column, float charWidth)
  67. {
  68. _sheet.SetColumnWidth(column, (int)Math.Round(charWidth * 256));
  69. return this;
  70. }
  71. public ISheet MergeCells(int firstRow, int lastRow, int firstColumn, int lastColumn)
  72. {
  73. var range = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
  74. _sheet.AddMergedRegion(range);
  75. return this;
  76. }
  77. }
  78. public class Row : IRow
  79. {
  80. private NRow _row;
  81. public int RowNumber => _row.RowNum;
  82. internal Row(NRow row)
  83. {
  84. _row = row;
  85. }
  86. public string ExtractString(int column, bool uppercase = false)
  87. {
  88. try
  89. {
  90. var result = "";
  91. var cell = _row.GetCell(column, MissingCellPolicy.CREATE_NULL_AS_BLANK);
  92. if (cell.CellType == CellType.Numeric)
  93. result = cell.NumericCellValue.ToString();
  94. else
  95. result = cell.StringCellValue;
  96. if (string.IsNullOrWhiteSpace(result))
  97. result = "";
  98. return uppercase ? result.ToUpper() : result;
  99. }
  100. catch (Exception e)
  101. {
  102. throw new Exception(string.Format("Row {0}:[{1}:{2}]: {3}", _row.Sheet.SheetName, _row.RowNum + 1, column, e.Message));
  103. }
  104. }
  105. public DateTime ExtractDateTime(int column)
  106. {
  107. try
  108. {
  109. var cell = _row.GetCell(column, MissingCellPolicy.CREATE_NULL_AS_BLANK);
  110. try
  111. {
  112. return cell.DateCellValue;
  113. }
  114. catch
  115. {
  116. var sDate = cell.StringCellValue;
  117. DateTime.TryParse(sDate, out var result);
  118. return result;
  119. }
  120. }
  121. catch (Exception e)
  122. {
  123. throw new Exception(string.Format("Row {0}:[{1}:{2}]: {3}", _row.Sheet.SheetName, _row.RowNum + 1, column, e.Message));
  124. }
  125. }
  126. public double? ExtractDouble(int column)
  127. {
  128. try
  129. {
  130. double result = 0.0F;
  131. var cell = _row.GetCell(column, MissingCellPolicy.CREATE_NULL_AS_BLANK);
  132. if (cell.CellType == CellType.Numeric || cell.CellType == CellType.Formula)
  133. result = cell.NumericCellValue;
  134. else if (cell.CellType == CellType.String)
  135. result = double.Parse(cell.StringCellValue);
  136. return result;
  137. }
  138. catch (FormatException)
  139. {
  140. return null;
  141. }
  142. catch (Exception e)
  143. {
  144. throw new Exception(string.Format("Row {0}:[{1}:{2}]: {3}", _row.Sheet.SheetName, _row.RowNum + 1, column, e.Message));
  145. }
  146. }
  147. public int GetColumn(string name, bool throwException = true)
  148. {
  149. var cells = _row.GetEnumerator();
  150. while (cells.MoveNext())
  151. {
  152. var cell = cells.Current;
  153. if (!string.IsNullOrWhiteSpace(cell.StringCellValue) && cell.StringCellValue.ToUpper().Trim().Equals(name.ToUpper().Trim()))
  154. {
  155. return cell.ColumnIndex;
  156. }
  157. }
  158. if (!throwException)
  159. {
  160. return -1;
  161. }
  162. throw new Exception("Unable to find Column: " + name);
  163. }
  164. public ICell GetCell(int column) => new Cell(_row.GetCell(column));
  165. public ICell NewCell(int column)
  166. {
  167. var cell = _row.CreateCell(column);
  168. return new Cell(cell);
  169. }
  170. }
  171. public class Cell : ICell
  172. {
  173. private NCell _cell;
  174. internal Cell(NCell cell)
  175. {
  176. _cell = cell;
  177. }
  178. public string GetValue()
  179. {
  180. if (_cell.CellType == CellType.Formula)
  181. {
  182. if (_cell.CachedFormulaResultType == CellType.Numeric)
  183. return string.Format("{0:F}", _cell.NumericCellValue.ToString());
  184. return _cell.StringCellValue;
  185. }
  186. return _cell.ToString();
  187. }
  188. public bool? GetBoolValue()
  189. {
  190. try
  191. {
  192. if (_cell.CellType == CellType.Boolean)
  193. return _cell.BooleanCellValue;
  194. return null;
  195. }
  196. catch (Exception)
  197. {
  198. return null;
  199. }
  200. }
  201. public double? GetDoubleValue()
  202. {
  203. try
  204. {
  205. double result = 0.0F;
  206. if (_cell.CellType == CellType.Numeric || _cell.CellType == CellType.Formula)
  207. result = _cell.NumericCellValue;
  208. else if (_cell.CellType == CellType.String)
  209. result = double.Parse(_cell.StringCellValue);
  210. return result;
  211. }
  212. catch (Exception)
  213. {
  214. return null;
  215. }
  216. }
  217. public DateTime GetDateTimeValue()
  218. {
  219. try
  220. {
  221. return _cell.DateCellValue;
  222. }
  223. catch
  224. {
  225. var sDate = _cell.StringCellValue;
  226. if(!DateTime.TryParse(sDate, out var result)){
  227. return DateTime.MinValue;
  228. }
  229. return result;
  230. }
  231. }
  232. public byte? GetByteValue()
  233. {
  234. try
  235. {
  236. byte result = 0;
  237. if (_cell.CellType == CellType.Numeric || _cell.CellType == CellType.Formula)
  238. result = (byte)_cell.NumericCellValue;
  239. else if (_cell.CellType == CellType.String)
  240. result = byte.Parse(_cell.StringCellValue);
  241. return result;
  242. }
  243. catch (Exception)
  244. {
  245. return null;
  246. }
  247. }
  248. public ICell SetValue(bool value)
  249. {
  250. _cell.SetCellValue(value);
  251. return this;
  252. }
  253. public ICell SetValue(double value)
  254. {
  255. _cell.SetCellValue(value);
  256. return this;
  257. }
  258. public ICell SetValue(string value)
  259. {
  260. _cell.SetCellValue(value);
  261. return this;
  262. }
  263. public ICell SetValue(byte value)
  264. {
  265. _cell.SetCellValue(value);
  266. return this;
  267. }
  268. public ICell SetValue(DateTime value)
  269. {
  270. _cell.SetCellValue(value);
  271. return this;
  272. }
  273. public ICell SetBlank()
  274. {
  275. _cell.SetBlank();
  276. return this;
  277. }
  278. public ICell SetStyle(ICellStyle style)
  279. {
  280. _cell.CellStyle = (style as CellStyle)._style;
  281. return this;
  282. }
  283. }
  284. public class SheetEnumerator : IEnumerator<Sheet>
  285. {
  286. public Sheet Current => new(_enumerator.Current);
  287. private IEnumerator<NSheet> _enumerator { get; }
  288. object IEnumerator.Current => new Sheet(_enumerator.Current);
  289. internal SheetEnumerator(IEnumerator<NSheet> enumerator)
  290. {
  291. _enumerator = enumerator;
  292. }
  293. public void Dispose()
  294. {
  295. _enumerator.Dispose();
  296. }
  297. public bool MoveNext()
  298. {
  299. return _enumerator.MoveNext();
  300. }
  301. public void Reset()
  302. {
  303. _enumerator.Reset();
  304. }
  305. }
  306. public class DataFormat : IDataFormat
  307. {
  308. public short FormatIndex { get; }
  309. public DataFormat(short format)
  310. {
  311. FormatIndex = format;
  312. }
  313. }
  314. public class CellStyle : ICellStyle
  315. {
  316. internal NCellStyle _style { get; }
  317. public IDataFormat DataFormat {
  318. get => new DataFormat(_style.DataFormat);
  319. set => _style.DataFormat = value.FormatIndex;
  320. }
  321. public CellStyle(NCellStyle style)
  322. {
  323. _style = style;
  324. }
  325. }
  326. public class Spreadsheet : ISpreadsheet
  327. {
  328. public IWorkbook Workbook;
  329. private NCellStyle DateStyle;
  330. private NDataFormat DataFormat;
  331. private Spreadsheet(IWorkbook workbook)
  332. {
  333. Workbook = workbook;
  334. DataFormat = Workbook.CreateDataFormat();
  335. }
  336. public Spreadsheet(string fileName) : this(WorkbookFactory.Create(fileName)) { }
  337. public Spreadsheet(FileStream file) : this(WorkbookFactory.Create(file)) { }
  338. public Spreadsheet() : this(new XSSFWorkbook()) { }
  339. public ISheet GetSheet(int index)
  340. {
  341. return new Sheet(Workbook.GetSheetAt(index));
  342. }
  343. public ISheet GetSheet(string name)
  344. {
  345. return new Sheet(Workbook.GetSheet(name));
  346. }
  347. public IEnumerator<ISheet> SheetEnumerator()
  348. {
  349. var enumerator = Workbook.GetEnumerator();
  350. return new SheetEnumerator(enumerator);
  351. }
  352. public IEnumerable<ISheet> Sheets()
  353. {
  354. for (var i = 0; i < Workbook.NumberOfSheets; i++)
  355. yield return GetSheet(i);
  356. }
  357. public void Write(FileStream file)
  358. {
  359. Workbook.Write(file);
  360. }
  361. public void Write(string filename, FileMode mode = FileMode.Create)
  362. {
  363. using(var stream = new FileStream(filename, FileMode.Create))
  364. {
  365. Workbook.Write(stream);
  366. }
  367. }
  368. public ISheet NewSheet(string name)
  369. {
  370. var sheet = Workbook.CreateSheet(name);
  371. return new Sheet(sheet);
  372. }
  373. public ISheet NewSheet()
  374. {
  375. var sheet = Workbook.CreateSheet();
  376. return new Sheet(sheet);
  377. }
  378. public ICellStyle NewStyle()
  379. {
  380. var style = Workbook.CreateCellStyle();
  381. var x = style.GetDataFormatString();
  382. return new CellStyle(style);
  383. }
  384. public IDataFormat GetDataFormat(string format)
  385. {
  386. var dataFormat = DataFormat.GetFormat(format);
  387. return new DataFormat(dataFormat);
  388. }
  389. }
  390. }