繁体   English   中英

如何从asp.net mvc更新和保存Excel文件?

[英]How can I update and save an excel file from asp.net mvc?

我有一个现有的delphi桌面应用程序,正在将其重写为asp.net mvc应用程序。

桌面应用程序包含大约120个excel报告。 这些报告通常只有几个包含设置信息(客户端ID等)的命名单元格,一些返回到sql server数据的数据查询以及一些关键表。

为了在桌面应用程序上生成报告,我使用ole自动化

  1. 打开报告
  2. 用正确的数据填充命名的单元格
  3. 使用ActiveWorkbook.RefreshAll()更新查询和数据透视表
  4. 保存报告

我想在我的Web应用程序中执行此操作。 但是,ole自动化不支持在服务器上,并且不起作用。 我见过的所有excel组件似乎都不支持刷新查询和/或关键表。

目前,我最好的选择似乎是使用某些报告生成器重写报告,并将其导出到excel。 但是,生成的文件写入时间较长,功能较少(没有枢轴表),当然有120个。

关于如何使用现有报告的任何建议?

更新资料

Excel已安装在服务器上,与开发计算机上的版本相同。

我的mvc代码类似于:

objApp = new Application();
objBooks = objApp.Workbooks;
objBook = objBooks.Open(FileName);
objApp.DisplayAlerts = false;  // don't warn if pivot table changed
objApp.ActiveWorkbook.RefreshAll();
objBook.SaveAs(newFileName);

在开发机器上,它工作正常,但在服务器上,它在第一行失败

objApp = new Application();

带有System.UnauthorizedAccessException的错误:由于以下错误,检索具有CLSID {00024500-0000-0000-C000-000000000046}的组件的COM类工厂失败:80070005访问被拒绝。 (来自HRESULT的异常:0x80070005(E_ACCESSDENIED))。

这是一个非常常见的错误,但是需要在服务器上设置许多项目才能与ASP.NET一起使用。 通常,有关此线程的建议就足够了: System.UnauthorizedAccessException:检索Word Interop的COM类工厂失败,错误80070005

似乎没有正确,彻底地处理过这些问题。 后期绑定也可能是问题的一部分。

我没有使用过Charts,但是我完全推荐EPPlus ,它是用于创建Excel工作簿的开源库。

看一眼 非营利组织

没错,您可能不想在服务器上执行OLE自动化。 只有内存泄漏和Excel实例在后台不受管理地运行的风险是无法实现的。

我们在Aspose.Cells方面拥有丰富的经验。 也许它支持您正在寻找的刷新功能?

几个月前,我发现了这个类,我曾经不使用excel来编写excel。 它像一种魅力一样工作,我在许多ASP.net应用程序中都使用它。 老实说,我不记得我从哪里得到的,所以即使他们应得的,我也不能给那个人创造。

/// <summary>
/// Produces Excel file without using Excel
/// </summary>
public class ExcelWriter
{
private Stream stream;
private BinaryWriter writer;

private ushort[] clBegin = { 0x0809, 8, 0, 0x10, 0, 0 };
private ushort[] clEnd = { 0x0A, 00 };


private void WriteUshortArray(ushort[] value)
{
    for (int i = 0; i < value.Length; i++)
        writer.Write(value[i]);
}

/// <summary>
/// Initializes a new instance of the <see cref="ExcelWriter"/> class.
/// </summary>
/// <param name="stream">The stream.</param>
public ExcelWriter(Stream stream)
{
    this.stream = stream;
    writer = new BinaryWriter(stream);
}

/// <summary>
/// Writes the text cell value.
/// </summary>
/// <param name="row">The row.</param>
/// <param name="col">The col.</param>
/// <param name="value">The string value.</param>
public void WriteCell(int row, int col, string value)
{
    ushort[] clData = { 0x0204, 0, 0, 0, 0, 0 };
    int iLen = value.Length;
    byte[] plainText = Encoding.ASCII.GetBytes(value);
    clData[1] = (ushort)(8 + iLen);
    clData[2] = (ushort)row;
    clData[3] = (ushort)col;
    clData[5] = (ushort)iLen;
    WriteUshortArray(clData);
    writer.Write(plainText);
}

/// <summary>
/// Writes the integer cell value.
/// </summary>
/// <param name="row">The row number.</param>
/// <param name="col">The column number.</param>
/// <param name="value">The value.</param>
public void WriteCell(int row, int col, int value)
{
    ushort[] clData = { 0x027E, 10, 0, 0, 0 };
    clData[2] = (ushort)row;
    clData[3] = (ushort)col;
    WriteUshortArray(clData);
    int iValue = (value << 2) | 2;
    writer.Write(iValue);
}

/// <summary>
/// Writes the double cell value.
/// </summary>
/// <param name="row">The row number.</param>
/// <param name="col">The column number.</param>
/// <param name="value">The value.</param>
public void WriteCell(int row, int col, double value)
{
    ushort[] clData = { 0x0203, 14, 0, 0, 0 };
    clData[2] = (ushort)row;
    clData[3] = (ushort)col;
    WriteUshortArray(clData);
    writer.Write(value);
}

/// <summary>
/// Writes the empty cell.
/// </summary>
/// <param name="row">The row number.</param>
/// <param name="col">The column number.</param>
public void WriteCell(int row, int col)
{
    ushort[] clData = { 0x0201, 6, 0, 0, 0x17 };
    clData[2] = (ushort)row;
    clData[3] = (ushort)col;
    WriteUshortArray(clData);
}

/// <summary>
/// Must be called once for creating XLS file header
/// </summary>
public void BeginWrite()
{
    WriteUshortArray(clBegin);
}

/// <summary>
/// Ends the writing operation, but do not close the stream
/// </summary>
public void EndWrite()
{
    WriteUshortArray(clEnd);
    writer.Flush();
}
}

只需将此代码复制到.cs文件中即可。

这是一个例子

    ExcelWriter writer = null;
    FileStream stream = null;
    string result = string.Empty;

        string filepath = path;
        DateTime sd = Convert.ToDateTime(sdate);
        DateTime ed = Convert.ToDateTime(edate);
        string daterange = sd.Month.ToString() + sd.Day.ToString() + sd.Year.ToString() + "_" + ed.Month.ToString() + ed.Day.ToString() + ed.Year.ToString();
        string xls = filepath + filename + "_" + daterange + ".xls";

        if (File.Exists(xls))
        {
            File.Delete(xls);
        }

        stream = new FileStream(xls, FileMode.Create);
        writer = new ExcelWriter(stream);
        writer.BeginWrite();

        //write header

        writer.WriteCell(0, 0, "text");
        writer.WriteCell(0, 1, "text");
        writer.WriteCell(0, 2, "text");


        //write data
        int row = 1;

        //Open Connection
        OpenDBConnection();

        //get Case List
        List<Int32> caseList = getCaseList(sdate, edate);

        foreach (Int32 caseid in caseList)
        {
            writer.WriteCell(row, 0, caseid);
            writer.WriteCell(row, 1, caseid);
            writer.WriteCell(row, 2, caseid);
            row++;
        }

        writer.EndWrite();
        stream.Close();`

可能您遇到了我几个月前遇到的相同问题。 问题在于,默认情况下,Microsoft Excel作为COM对象只能由管理员,系统或交互式帐户激活。

这是为我工作的详细解决方案: http : //blog.crowe.co.nz/archive/2006/03/02/589.aspx

希望这可以帮助。

ps:关于OLE DB,可以更改代码以使用OleDbConnection吗?

您是正确的,MS绝对不支持。 但是,ole自动化应该在服务器上工作。 这是一个愚蠢的问题,您是否在服务器上安装了Excel? 您可以发送示例代码吗? 我通常使用互操作性。 这是一个简单的示例: http : //dotnetperls.com/excel

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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