EPPlus:支持自动保存功能吗?

时间:2015-06-30 10:22:26

标签: c# export-to-excel epplus epplus-4

我打算使用EPPlus(4.0.4版)库将我的实时数据导出到我的WPF应用程序中使用C#.NET的Excel工作表。然而,我的问题是EPPLus库特有的。

我已经浏览了EPPlus示例(),其中您可以使用SetValue将值写出到工作表。

问题在于,由于我的应用程序需要在几天的时间内写出实时数据(!),我想确保每隔一段时间保存一次我的数据,以避免数据丢失。应用程序/系统崩溃。

通常,我希望有一个自动保存功能,其中一个可以保存当前状态,然后继续正常添加新记录。

然而,EPPlus似乎没有这个(?)......我将如何实现这一目标?

示例源代码

using (ExcelPackage package = new ExcelPackage())
{
      //Load the sheet with one string column, one date column and a few random numbers.
    var ws = package.Workbook.Worksheets.Add("Performance Test");

    //Format all cells
    ExcelRange cols = ws.Cells["A:XFD"];
    cols.Style.Fill.PatternType = ExcelFillStyle.Solid;
    cols.Style.Fill.BackgroundColor.SetColor(Color.LightGray);

    var rnd = new Random();                
    for (int row = 1; row <= Rows; row++)
    {
        ws.SetValue(row, 1, row);
        ws.SetValue(row, 2, string.Format("Row {0}", row));
        ws.SetValue(row, 3, DateTime.Today.AddDays(row));
        ws.SetValue(row, 4, rnd.NextDouble() * 10000);
        ws.SetValue(row, 5, rnd.NextDouble() * 100);
        ws.SetValue(row, 6, rnd.NextDouble() * 10);
        ws.SetValue(row, 7, rnd.NextDouble() * 78);
        ws.SetValue(row, 8, rnd.NextDouble() * 5300);
        ws.SetValue(row, 9, rnd.NextDouble() * 1250);
        ws.SetValue(row, 10, rnd.NextDouble() * 670);

        if (row % 10000 == 0)
        {
            Console.WriteLine("{0:HH.mm.ss}\tWriting row {1}...", DateTime.Now, row);

            //I need a way to save the existing data say every 10K records or so.

        }
    }             

    ws.Select("C2");
    Console.WriteLine("{0:HH.mm.ss}\tSaving...", DateTime.Now);
    package.Compression = CompressionLevel.BestSpeed;
    package.SaveAs(newFile); //this seems to be done only at the end of processing!
}

3 个答案:

答案 0 :(得分:2)

AutoSave它通常用于基于用户界面的程序。 EPPlus不是。

你必须自己做。只需每隔一段时间拨打if,也许在你的循环中。你似乎已经有{{1}}了。

答案 1 :(得分:2)

为什么不在每批后保存并打开现有的xls&amp;做更新&amp;再次保存?

就像

一样
ExcelPackage package = new ExcelPackage(newFile);

(*请注意,newFile只是变量名,在此上下文中,它更像existingFile

你不会丢失你在床单中已有的东西,你只需要找到最后一行继续你上次结束的地方:

ws.Dimension.End.Row;

作为奖励,您不会阻止用户访问文件(您的应用程序现在保留写入权限和阻止文件)以保存自己的更改(比方说,他在他的数据中添加了“他想要的免费且非常酷的图表”之后':))

答案 2 :(得分:0)

我已经接受了Jan'splite'Kondelík作为解决方案的答案,因为它提供了解决问题所需的信息。

但是,我发布了自己的示例,以帮助其他用户更快地达到Jan建议的解决方案。

基本上,重新打开文件时,需要在ExcelPackage()构造函数中传递文件的名称。此外,您可以通过传递现有工作表的名称或下面的索引来获取对所需工作表的引用

package.Workbook.Worksheets["PerformanceTest"] 

OR

package.Workbook.Worksheets[1] //1 to n, 1 being base

我发布的示例有助于演示如何实现“自动保存”逻辑。希望这也有助于其他人。

我在C#中创建了一个控制台应用程序来演示这个。

示例代码

<强> Program.cs的

using System;
using System.IO;

namespace EPPlus_AutoSave_Excel_Export
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo outputDir = new DirectoryInfo(@"c:\temp\Auto-Save");

            if (!outputDir.Exists) 
                throw new Exception("outputDir does not exist!");

            Sample_Auto_Save obj = new Sample_Auto_Save(outputDir, 50000);
            obj.ExportWithAutoSave();
        }
    }
}

<强> Sample_Auto_Save.cs

using OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.IO;
using System.Drawing;

namespace EPPlus_AutoSave_Excel_Export
{
    class Sample_Auto_Save
    {
        int Rows;
        int nRowsWritten = 0;
        bool bAppendData = false;
        ExcelWorksheet ws;
        DirectoryInfo outputDir;


        public Sample_Auto_Save(DirectoryInfo outputDir, int Rows)
        {
            this.Rows = Rows;
            this.outputDir = outputDir;
        }

        public void ExportWithAutoSave()
        {

            FileInfo newFile = new FileInfo(outputDir.FullName + @"\Auto_Save_Export.xlsx");
            if (newFile.Exists)
            {
                newFile.Delete();  // ensures we create a new workbook
                newFile = new FileInfo(outputDir.FullName + @"\Auto_Save_Export.xlsx");
            }

            Console.WriteLine("{0:HH.mm.ss}\tStarting...", DateTime.Now);
            while (nRowsWritten < Rows)
            {
                if (bAppendData == false)
                {
                    using (ExcelPackage package = new ExcelPackage())
                    {

                        //Load the sheet with one string column, one date column and a few random numbers
                        ws = package.Workbook.Worksheets.Add("Performance Test");
                        InsertRows();
                        bAppendData = true;
                        AutoSave(newFile, package);
                    }
                }
                else
                {
                    using (ExcelPackage package = new ExcelPackage(newFile))
                    {
                        Console.WriteLine("{0:HH.mm.ss}\tOpening existing file again!...", DateTime.Now);
                        ws = package.Workbook.Worksheets["Performance Test"];

                        InsertRows();

                        AutoSave(newFile, package);
                    }
                }       
            }
            Console.WriteLine("{0:HH.mm.ss}\tDone!!", DateTime.Now);           
        }

        private void AutoSave(FileInfo newFile, ExcelPackage package)
        {
            ws.Select("C2");
            Console.WriteLine("{0:HH.mm.ss}\tAuto-Saving...", DateTime.Now);
            package.Compression = CompressionLevel.BestSpeed;
            package.SaveAs(newFile);
            bAppendData = true;
        }

        private void InsertRows()
        {

            //Format all cells
            ExcelRange cols = ws.Cells["A:XFD"];
            cols.Style.Fill.PatternType = ExcelFillStyle.Solid;
            cols.Style.Fill.BackgroundColor.SetColor(Color.LightGray);

            var rnd = new Random();
            int startRow;
            if (ws.Dimension == null)
                startRow = 0;
            else
                startRow = ws.Dimension.End.Row;
            for (int row = startRow + 1; row <= Rows; row++, nRowsWritten++)
            {
                ws.SetValue(row, 1, row);                               //The SetValue method is a little bit faster than using the Value property
                ws.SetValue(row, 2, string.Format("Row {0}", row));
                ws.SetValue(row, 3, DateTime.Now.ToShortTimeString());
                ws.SetValue(row, 4, rnd.NextDouble() * 10000);


                if (row % (Rows/5) == 0)
                {
                    Console.WriteLine("{0:HH.mm.ss}\tWritten {1} records!...", DateTime.Now, row);
                    nRowsWritten++;
                    return;
                }
            }
        }
    }
}

<强>更新: 看起来自动保存大文件的开销非常高。在与Jan和Patrick讨论后,我最终意识到最好将所有实时数据写入单独的数据文件,最后在测试结束时使用EPPlus导出到excel。这将是最快,最简单的方法!

或者,如果并非强制要求所有数据都存在于一个文件中,请考虑将数据拆分为多个Excel文件。例如,您可以为每个文件保存10K记录,这样,您可以同时确保速度,低内存要求和数据安全。