C#でEPPlusの既存のテーブルを拡張する方法はありますか?私のプログラムの仕組みは、2行だけのテーブルを作成し、さらに追加し続けることです。 ExcelTable
にどんな種類のサイズ変更方法も見つからないようです。これに専用の方法はありますか、それとも何らかの代替方法を使用する必要がありますか?
編集:わかりました。これを明確にします。 私はすでにEPPlusを動作させてExcelTableを作成しています。私の質問は:既存のExcelTableを大きくする(行を追加する)にはどうすればよいですか?
この質問は約1年前のものですが、誰かがまだ答えを必要としていることを期待して、EEPlus(v4.1で作業しています)のバグのために完全ではありませんが、直接的な解決策があります。
ExcelWorksheetには InsertRow(Int32、Int32、Int32) メソッドがあります。テーブルの一部である領域に行を挿入すると、テーブルも展開されます。境界を取得するには、Addressプロパティを使用するだけです。テーブルの最初の行と最後の行の間に挿入してください。
セルの検証に関連して私が知っている欠陥があります。既存の行からスタイルをコピーできるオーバーロードを使用しても、検証はコピーされません。さらに悪いことに、検証は元の場所に残され、セルとともにシフトされません。私はテストしていませんが、検証に範囲があり、ターゲットとしてセルがない場合、その範囲に行を挿入すると、その範囲も拡張されると思います。
これは、ワークシートにすでにあるデータのテーブルを展開する場合には役立ちませんが、行を移動することはできます。また、テーブルが並んでいる場合も同様です(これは悪夢です)。
残念ながら、直接的な方法はありません。理由はよくわかりませんが、EPPlusの開発者は、ExcelTable.Address
プロパティのみを準備することを選択しています。したがって、最も明白な選択は、新しいテーブルを作成し、すべてのプロパティをコピーして(必要なすべてのプロパティを知っていると仮定して)、古いテーブルを削除することです。何かを見逃す可能性があるため、あまり理想的ではありません。
しかし、他に2つあります。次はまったくきれいですが、コピー/削除よりも優れています。次のようなテーブルを想定します。
オプション1EPPlusソースコードをフォークして、必要なプロパティを読み取り/書き込みにすることができます。これは、ファイルExcelTable.cs
で次のように変更して行います。
public ExcelAddressBase Address
{
get
{
return _address;
}
internal set //REMOVE internal KEYWORD
{
_address = value;
SetXmlNodeString("@ref",value.Address);
WriteAutoFilter(ShowTotal);
}
}
internal
キーワードを削除します。しかしもちろん、そうすることで他の何かが途中で壊れないように注意する必要があります。これを使用すると、次のようなことができます。
var fileInfo = new FileInfo(@"c:\temp\Expand_Table.xlsx");
using (var pck = new ExcelPackage(fileInfo))
{
var workbook = pck.Workbook;
var worksheet = workbook.Worksheets.First();
//Added 11th data row assuming the table is from A1 to C11 (Header row + 10 data rows)
worksheet.Cells["A12"].Value = 10;
worksheet.Cells["B12"].Value = 100;
worksheet.Cells["C12"].Value = Path.GetRandomFileName();
var tbl = worksheet.Tables["TestTable1"];
var oldaddy = tbl.Address;
var newaddy = new ExcelAddressBase(oldaddy.Start.Row, oldaddy.Start.Column, oldaddy.End.Row + 1, oldaddy.End.Column);
tbl.Address = newaddy;
pck.Save();
}
オプション2はより安全なオプションですが、XMLで文字列置換を使用することで最も「ダーティ」になります。たとえば、オートフィルターをオンにすることができるため、アドレスへの参照が1つだけであるとは想定できません。 Excelでテーブルを作成すると、デフォルトのXMLは次のようになります(アドレスへの2つの参照に注意してください)。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="3" name="TestTable1" displayName="TestTable1" ref="A1:C11" totalsRowShown="0">
<autoFilter ref="A1:C11" />
<tableColumns count="3">
<tableColumn id="1" name="Col1" />
<tableColumn id="2" name="Col2" />
<tableColumn id="3" name="Col3" />
</tableColumns>
<tableStyleInfo name="TableStyleMedium2" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" />
</table>
したがって、次のように文字列の置換を行うことができます。
var fileInfo = new FileInfo(@"c:\temp\Expand_Table.xlsx");
using (var pck = new ExcelPackage(fileInfo))
{
var workbook = pck.Workbook;
var worksheet = workbook.Worksheets.First();
//Added 11th data row assuming the table is from A1 to C11 (Header row + 10 data rows)
worksheet.Cells["A12"].Value = 10;
worksheet.Cells["B12"].Value = 100;
worksheet.Cells["C12"].Value = Path.GetRandomFileName();
var tbl = worksheet.Tables["TestTable1"];
var oldaddy = tbl.Address;
var newaddy = new ExcelAddressBase(oldaddy.Start.Row, oldaddy.Start.Column, oldaddy.End.Row + 1, oldaddy.End.Column);
//Edit the raw XML by searching for all references to the old address
tbl.TableXml.InnerXml = tbl.TableXml.InnerXml.Replace(oldaddy.ToString(), newaddy.ToString());
pck.Save();
}
同じ問題が発生し、SQLDataTableをExcelテーブルにダンプする非常に高速な方法を見つけました。
わずか04.2秒で18004行
私のテンプレートには、テーブルを拡張するときに新しい行に継承される数式が含まれていました。
Template.xlsx
Report_with_Epplus.xlsx
public void xlsEpplus()
{
try
{
TimeSpan stop;
TimeSpan start = new TimeSpan(DateTime.Now.Ticks);
Database DB = new Database();
DB.msConect();
string sql = "SELECT * FROM table_test";
DataTable dt_tab = DB.xSqlMs(sql);
string Template = "D:\\Plantillas\\Template.xlsx";
string filePath = "D:\\Plantillas\\Report_with_Epplus.xlsx";
File.Copy(Template, filePath, true);
ExcelPackage pck = new ExcelPackage();
pck.Load(new FileStream(Template, FileMode.OpenOrCreate));
ExcelWorksheet ws = pck.Workbook.Worksheets.First();
var a = ws.Cells["A1"].Value;
int i = 2;
ws.InsertRow(i, dt_tab.Rows.Count);
ws.Cells["A2"].LoadFromDataTable(dt_tab, true);
pck.SaveAs(new FileInfo(filePath));
stop = new TimeSpan(DateTime.Now.Ticks);
Console.WriteLine("xlsEpplus_While:" + stop.Subtract(start));
}
catch (Exception ex)
{
//
Console.WriteLine("ERROR: " + ex.Message);
}
}