Add Excel Table classes
This commit is contained in:
parent
cdb153c988
commit
f01228d945
47
RhSolutions.AddIn/ExcelTable/ExcelColumn.cs
Normal file
47
RhSolutions.AddIn/ExcelTable/ExcelColumn.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public sealed class ExcelColumn : ExcelTable, IEnumerable<ExcelTableCell>
|
||||
{
|
||||
public string Header
|
||||
{
|
||||
get => Range.Cells[1, 1].Value.ToString();
|
||||
}
|
||||
public int Index
|
||||
{
|
||||
get => Range.Column - ParentTable.Range.Column;
|
||||
}
|
||||
public int Length
|
||||
{
|
||||
get => Range.Rows.Count;
|
||||
}
|
||||
|
||||
public ExcelColumn(Range range, ExcelTable table) : base(range, table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
|
||||
public ExcelTableCell this[int index]
|
||||
{
|
||||
get => new(Range.Cells[index + 1, 1], ParentTable);
|
||||
}
|
||||
|
||||
public IEnumerator<ExcelTableCell> GetEnumerator()
|
||||
{
|
||||
return new ExcelColumnEnumerator(Range, ParentTable);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
|
||||
public ExcelColumn AddLeft()
|
||||
{
|
||||
Range.EntireColumn
|
||||
.Insert(XlInsertShiftDirection.xlShiftToRight,
|
||||
XlInsertFormatOrigin.xlFormatFromRightOrBelow);
|
||||
|
||||
return ParentTable.Columns[this.Index - 1];
|
||||
}
|
||||
}
|
54
RhSolutions.AddIn/ExcelTable/ExcelColumnEnumerator.cs
Normal file
54
RhSolutions.AddIn/ExcelTable/ExcelColumnEnumerator.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelColumnEnumerator : IEnumerator<ExcelTableCell>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
private int position = 0;
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelTableCell Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcelTableCell(Range.Cells[position, 1], ParentTable);
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelColumnEnumerator(Range range, ExcelTable table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return (position <= Range.Rows.Count);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
39
RhSolutions.AddIn/ExcelTable/ExcelColumns.cs
Normal file
39
RhSolutions.AddIn/ExcelTable/ExcelColumns.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelColumns : IEnumerable<ExcelColumn>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
public int Length
|
||||
{
|
||||
get => Range.Columns.Count;
|
||||
}
|
||||
|
||||
public ExcelColumns(Range range, ExcelTable parentTable)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = parentTable;
|
||||
}
|
||||
|
||||
public ExcelColumn this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index + 1 > Range.Columns.Count)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return new ExcelColumn(Range.Columns[index + 1], ParentTable);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<ExcelColumn> GetEnumerator()
|
||||
{
|
||||
return new ExcelColumnsEnumerator(Range, ParentTable);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
54
RhSolutions.AddIn/ExcelTable/ExcelColumnsEnumerator.cs
Normal file
54
RhSolutions.AddIn/ExcelTable/ExcelColumnsEnumerator.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelColumnsEnumerator: IEnumerator<ExcelColumn>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
private int position = 0;
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelColumn Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcelColumn(Range.Columns[position], ParentTable);
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelColumnsEnumerator(Range range, ExcelTable table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return (position <= Range.Columns.Count);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
33
RhSolutions.AddIn/ExcelTable/ExcelRow.cs
Normal file
33
RhSolutions.AddIn/ExcelTable/ExcelRow.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public sealed class ExcelRow : ExcelTable, IEnumerable<ExcelTableCell>
|
||||
{
|
||||
public int Index
|
||||
{
|
||||
get => Range.Row - ParentTable.Range.Row;
|
||||
}
|
||||
public int Length
|
||||
{
|
||||
get => Range.Columns.Count;
|
||||
}
|
||||
|
||||
public ExcelRow(Range range, ExcelTable table) : base(range, table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
|
||||
public ExcelTableCell this[int index]
|
||||
{
|
||||
get => new(Range.Cells[1, index + 1], ParentTable);
|
||||
}
|
||||
|
||||
public IEnumerator<ExcelTableCell> GetEnumerator()
|
||||
{
|
||||
return new ExcelRowEnumerator(Range, ParentTable);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
54
RhSolutions.AddIn/ExcelTable/ExcelRowEnumerator.cs
Normal file
54
RhSolutions.AddIn/ExcelTable/ExcelRowEnumerator.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelRowEnumerator : IEnumerator<ExcelTableCell>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
private int position = 0;
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelTableCell Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcelTableCell(Range.Cells[1, position], ParentTable);
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelRowEnumerator(Range range, ExcelTable parentTable)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = parentTable;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return (position <= Range.Columns.Count);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
39
RhSolutions.AddIn/ExcelTable/ExcelRows.cs
Normal file
39
RhSolutions.AddIn/ExcelTable/ExcelRows.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelRows : IEnumerable<ExcelRow>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
public int Length
|
||||
{
|
||||
get => Range.Rows.Count;
|
||||
}
|
||||
|
||||
public ExcelRows(Range range, ExcelTable parentTable)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = parentTable;
|
||||
}
|
||||
|
||||
public ExcelRow this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index + 1 > Range.Rows.Count)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return new ExcelRow(Range.Rows[index + 1], ParentTable);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<ExcelRow> GetEnumerator()
|
||||
{
|
||||
return new ExcelRowsEnumerator(Range, ParentTable);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
55
RhSolutions.AddIn/ExcelTable/ExcelRowsEnumerator.cs
Normal file
55
RhSolutions.AddIn/ExcelTable/ExcelRowsEnumerator.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelRowsEnumerator : IEnumerator<ExcelRow>
|
||||
{
|
||||
public Range Range { get; }
|
||||
public ExcelTable ParentTable { get; }
|
||||
private int position = 0;
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelRow Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcelRow(Range.Rows[position], ParentTable);
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExcelRowsEnumerator(Range range, ExcelTable table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return (position <= Range.Rows.Count);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
53
RhSolutions.AddIn/ExcelTable/ExcelTable.cs
Normal file
53
RhSolutions.AddIn/ExcelTable/ExcelTable.cs
Normal file
@ -0,0 +1,53 @@
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public class ExcelTable
|
||||
{
|
||||
public Range Range { get; protected set; }
|
||||
public ExcelTable ParentTable { get; protected set; }
|
||||
public ExcelRows Rows { get; }
|
||||
public ExcelColumns Columns { get; }
|
||||
|
||||
public ExcelTable(Range range)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = null;
|
||||
Rows = new ExcelRows(Range, this);
|
||||
Columns = new ExcelColumns(Range, this);
|
||||
}
|
||||
|
||||
public ExcelTable(Range range, ExcelTable table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
Rows = new ExcelRows(Range, this);
|
||||
Columns = new ExcelColumns(Range, this);
|
||||
}
|
||||
|
||||
public ExcelTableCell this[int row, int column]
|
||||
{
|
||||
get => new(Range.Cells[row + 1, column + 1], this);
|
||||
}
|
||||
|
||||
public IEnumerable<ExcelTableCell> Find(object item)
|
||||
{
|
||||
Range firstFound = Range.Find(item);
|
||||
if (firstFound == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
Range nextFound = firstFound;
|
||||
|
||||
while (true)
|
||||
{
|
||||
yield return new ExcelTableCell(nextFound, ParentTable ?? this);
|
||||
nextFound = Range.FindNext(nextFound);
|
||||
|
||||
if (nextFound.Row == firstFound.Row
|
||||
&& nextFound.Column == firstFound.Column)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
RhSolutions.AddIn/ExcelTable/ExcelTableCell.cs
Normal file
24
RhSolutions.AddIn/ExcelTable/ExcelTableCell.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace RhSolutions.ExcelTable;
|
||||
|
||||
public sealed class ExcelTableCell : ExcelTable
|
||||
{
|
||||
public ExcelRow ParentRow
|
||||
{
|
||||
get => ParentTable.Rows[ParentTable.Range.Row - Range.Row];
|
||||
}
|
||||
public ExcelColumn ParentColumn
|
||||
{
|
||||
get => ParentTable.Columns[ParentTable.Range.Column - Range.Column];
|
||||
}
|
||||
public object Value
|
||||
{
|
||||
get => Range.Cells[1, 1].Value2;
|
||||
set => Range.Cells[1, 1].Value2 = value;
|
||||
}
|
||||
|
||||
public ExcelTableCell(Range range, ExcelTable table) : base(range, table)
|
||||
{
|
||||
Range = range;
|
||||
ParentTable = table;
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<TargetFrameworks>net472;net6.0-windows7.0</TargetFrameworks>
|
||||
<LangVersion>10</LangVersion>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>RhSolutions.AddIn</RootNamespace>
|
||||
<RootNamespace>RhSolutions</RootNamespace>
|
||||
<AssemblyName>RhSolutions.AddIn</AssemblyName>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
65
RhSolutions.Tests/ExcelTablesTests.cs
Normal file
65
RhSolutions.Tests/ExcelTablesTests.cs
Normal file
@ -0,0 +1,65 @@
|
||||
namespace RhSolutions.Tests;
|
||||
|
||||
[ExcelTestSettings(OutOfProcess = true, Workbook = @"TestWorkbooks\ExcelTableTest.xlsx")]
|
||||
public class ExcelTablesTests : IDisposable
|
||||
{
|
||||
ExcelTable.ExcelTable table;
|
||||
|
||||
public ExcelTablesTests()
|
||||
{
|
||||
Util.Application.Workbooks.Add();
|
||||
|
||||
Worksheet worksheet = Util.Workbook.Sheets[1];
|
||||
Range range = worksheet.Range["E7:G9"];
|
||||
table = new(range);
|
||||
}
|
||||
|
||||
[ExcelFact]
|
||||
public void CanReadExcelTable()
|
||||
{
|
||||
Assert.Equal(3, table.Columns.Where(c => c.Header.StartsWith("Столбец")).Count());
|
||||
Assert.Equal("Столбец 1", table.Rows.First()[0].Value);
|
||||
Assert.Equal("Столбец 2", table[0, 1].Value);
|
||||
Assert.Equal(123d, table[1, 1].Value);
|
||||
Assert.Null(table[1, 2].Value);
|
||||
}
|
||||
|
||||
[ExcelFact]
|
||||
public void CanModifyTableCells()
|
||||
{
|
||||
table[2, 1].Value = 1;
|
||||
table[1, 1].Value = (double)table[1, 1].Value + 123;
|
||||
Assert.Equal(1d, table[2, 1].Value);
|
||||
Assert.Equal(246d, table[1, 1].Value);
|
||||
}
|
||||
|
||||
[ExcelFact]
|
||||
public void CanFindInTable()
|
||||
{
|
||||
table[2, 0].Value = "Find!";
|
||||
table[2, 1].Value = "Find this!";
|
||||
table[2, 2].Value = "Find that!";
|
||||
|
||||
|
||||
var cells = table.Find("Find");
|
||||
Assert.Collection(cells, item => Assert.Equal("Find!", item.Value),
|
||||
item => Assert.Equal("Find this!", item.Value),
|
||||
item => Assert.Equal("Find that!", item.Value));
|
||||
Assert.Equal(0, table.Find("Значение").First().ParentColumn.Index);
|
||||
Assert.Equal(3, table.Rows[2].Find("Find").Count());
|
||||
Assert.Empty(table.Columns[1].Find("Пусто"));
|
||||
}
|
||||
|
||||
[ExcelFact]
|
||||
public void CanAddColumns()
|
||||
{
|
||||
int originalCount = table.Columns.Count();
|
||||
table.Columns[1].AddLeft();
|
||||
Assert.Equal(originalCount + 1, table.Columns.Count());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Util.Application.ActiveWindow.Close(SaveChanges: false);
|
||||
}
|
||||
}
|
@ -24,6 +24,9 @@
|
||||
<None Update="TestWorkbooks\EmptyWorkbook.xlsx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestWorkbooks\ExcelTableTest.xlsx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
BIN
RhSolutions.Tests/TestWorkbooks/ExcelTableTest.xlsx
Normal file
BIN
RhSolutions.Tests/TestWorkbooks/ExcelTableTest.xlsx
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
global using Xunit;
|
||||
global using Microsoft.Office.Interop.Excel;
|
||||
global using ExcelDna.Testing;
|
||||
global using RhSolutions.Models;
|
||||
global using RhSolutions.ExcelTable;
|
||||
global using RhSolutions.Services;
|
||||
|
@ -1,9 +1,9 @@
|
||||
namespace RhSolutions.Tests;
|
||||
|
||||
[ExcelTestSettings(OutOfProcess = true)]
|
||||
public class WorkbookCheck : IDisposable
|
||||
public class WorkbookValidationTests : IDisposable
|
||||
{
|
||||
public WorkbookCheck()
|
||||
public WorkbookValidationTests()
|
||||
{
|
||||
Util.Application.Workbooks.Add();
|
||||
}
|
||||
@ -11,7 +11,7 @@ public class WorkbookCheck : IDisposable
|
||||
[ExcelFact(Workbook = @"TestWorkbooks\EmptyTestTable.xlsx")]
|
||||
public void WorksheetIsCorrect()
|
||||
{
|
||||
Worksheet worksheet= Util.Workbook.Sheets[1];
|
||||
Worksheet worksheet = Util.Workbook.Sheets[1];
|
||||
Assert.True(worksheet.IsRehauSource());
|
||||
}
|
||||
|
||||
@ -24,6 +24,6 @@ public class WorkbookCheck : IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Util.Application.ActiveWorkbook.Close(SaveChanges: false);
|
||||
Util.Application.ActiveWindow.Close(SaveChanges: false);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user