Files
Gary Sharp 5ce9e51ae7 Feature: MS Excel (xlsx) Import/Export
Microsoft Excel files can be used to import/export devices. Several
import bugs were also fixed in the process.
2017-03-25 15:37:28 +11:00

134 lines
4.8 KiB
C#

using ClosedXML.Excel;
using Disco.Models.Services.Devices.Importing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Disco.Services.Devices.Importing
{
public class XlsxDeviceImportContext : BaseDeviceImportContext
{
private bool hasHeaderRow;
private List<object[]> rawData;
public XlsxDeviceImportContext(string Filename, bool HasHeaderRow, Stream XlsxStream)
: base(Filename)
{
hasHeaderRow = HasHeaderRow;
using (var stream = new MemoryStream((int)XlsxStream.Length))
{
XlsxStream.CopyTo(stream);
ParseXlsx(stream);
}
}
public override int RecordCount
{
get
{
return rawData.Count;
}
}
public override IDeviceImportDataReader GetDataReader()
{
return new XlsxDeviceImportDataReader(this, rawData, hasHeaderRow);
}
private void ParseXlsx(Stream XlsxStream)
{
using (var xlWorkbook = new XLWorkbook(XlsxStream, XLEventTracking.Disabled))
{
if (xlWorkbook.Worksheets.Count == 0)
throw new IndexOutOfRangeException("Workbook contains no worksheets");
// Use first worksheet
var worksheet = xlWorkbook.Worksheets.Worksheet(1);
SetDatasetName($"{Filename} [Sheet: {worksheet.Name}]");
var columnCount = worksheet.LastColumnUsed().ColumnNumber();
if (hasHeaderRow)
{
var headerRow = worksheet.FirstRow();
SetColumns(Enumerable.Range(1, columnCount)
.Select(i =>
{
var cell = headerRow.Cell(i);
var headerName = cell.GetString();
if (string.IsNullOrWhiteSpace(headerName))
{
headerName = $"Column {cell.WorksheetColumn().ColumnLetter()}";
}
return new DeviceImportColumn()
{
Index = i - 1,
Name = headerName,
Type = DeviceImportFieldTypes.IgnoreColumn
};
}));
}
else
{
SetColumns(Enumerable.Range(1, columnCount)
.Select(i => new DeviceImportColumn()
{
Index = i - 1,
Name = $"Column {worksheet.Column(i).ColumnLetter()}",
Type = DeviceImportFieldTypes.IgnoreColumn
}));
}
// Import Data
var rawData = new List<object[]>();
foreach (var row in worksheet.RowsUsed().Skip(hasHeaderRow ? 1 : 0))
{
var record = new object[columnCount];
rawData.Add(record);
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
{
var cell = row.Cell(columnIndex + 1);
var cellValue = cell.Value;
switch (cell.DataType)
{
case XLCellValues.Number:
if (cellValue is double)
{
record[columnIndex] = (double)cellValue;
}
continue;
case XLCellValues.Boolean:
if (cellValue is bool)
{
record[columnIndex] = (bool)cellValue;
}
continue;
case XLCellValues.DateTime:
if (cellValue is DateTime)
{
record[columnIndex] = (DateTime)cellValue;
}
continue;
}
var stringValue = cellValue == null ? null : cellValue.ToString();
if (stringValue != null && stringValue.Length == 0)
{
stringValue = null;
}
record[columnIndex] = stringValue;
}
}
this.rawData = rawData;
}
}
}
}