简体   繁体   中英

Expand a table in EPPlus C#

Is there any way that I can expand an existing table in EPPlus in C#. The way my program works is I create the table with only 2 rows and keep adding more. I just can't seem to find any sort of resize method in ExcelTable . Is there a dedicated method for this, or do I need to use some sort of alternative?

Edit: Okay I'm just going to clarify this. I already have EPPlus working and making an ExcelTable. My question is: How can I make an existing ExcelTable larger (add more rows)?

Unfortunately, there is no direct method. Not quite sure why but the developers of EPPlus choose to make the ExcelTable.Address property ready only. So the most obvious choose would be to create a new table, copy all of the properties (assuming you know all of them that are needed) and delete the old one. Not very ideal since you could miss something.

But I see two other others - next exactly pretty either but better then the copy/delete. Assume a table like so:

在此输入图像描述

Option 1 you could fork the EPPlus source code and make the property needed read/write. You would do this in the file ExcelTable.cs by changing:

    public ExcelAddressBase Address
    {
        get
        {
            return _address;
        }
        internal set  //REMOVE internal KEYWORD
        {
            _address = value;
            SetXmlNodeString("@ref",value.Address);
            WriteAutoFilter(ShowTotal);
        }
    }

by removing the internal keyword. But of course you will have to be careful doing so does not break something else along the way. With this, you can do something like:

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();
}

Option 2 would be the safer option but most "dirty" by using a string replace on the XML. We cant assume there is only one reference to the address because, for example, the AutoFilter could be turned on. Here is what the default XML will look like when you create a table in excel (note the 2 references to the address):

<?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>

So we can do a string replace like this:

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();
}

This question is about one year old, but hoping that someone still needs an answer, there is a direct solution, although not complete because of a bug in EEPlus (I am working with v4.1).

ExcelWorksheet has an InsertRow(Int32, Int32, Int32) method. If you insert rows in an area that is part of the table, the table is also expanded. Simply use it's Address property to get the bounds. Just make sure to insert between the first and last row of the table.

There is a flaw I know about related to cell validation: even if you use the overload which can copy style from an existing row, the validation is not copied. Even worse, the validation is left where it was and it is not shifted with the cells. I have not tested, but I believe that if the validation has a range and not a cell as target, that one is also expanded if you insert rows into that range.

This won't help you if you wish to expand the table on data aready in the Worksheet - but you can still move rows. And neither when you have many tables side-by-side (which is a nightmare).

I had the same problem and I found an extremely fast way to dump an SQL DataTable on an Excel Table.

18004 rows in just 04.2 seconds

My template contained formulas that when extending the table were inherited to the new rows.

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);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM