C# 与其他方法相比,Datatable与Excel互操作;“另存为/打开”时所需的弹出窗口

C# 与其他方法相比,Datatable与Excel互操作;“另存为/打开”时所需的弹出窗口,c#,excel,datatable,office-interop,export-to-excel,C#,Excel,Datatable,Office Interop,Export To Excel,我已经实现了以下方法,看起来效果不错,但是它将文件保存到预定义的位置,相反,我希望它为用户提供一个选项,就像任何常规的下载弹出窗口一样:打开、保存、另存为。有什么想法吗 为了克服“在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式”的异常,必须实现线程,请参见编辑 编辑: (一) (二) (三) 编辑结束 private static void ExportToExcel(DataTable dt) { Microsoft.Office.Interop.Excel.Ap

我已经实现了以下方法,看起来效果不错,但是它将文件保存到预定义的位置,相反,我希望它为用户提供一个选项,就像任何常规的下载弹出窗口一样:打开、保存、另存为。有什么想法吗


为了克服“在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式”的异常,必须实现线程,请参见编辑

编辑:

(一)

(二)

(三)

编辑结束

private static void ExportToExcel(DataTable dt)
{
    Microsoft.Office.Interop.Excel.ApplicationClass excel = new Microsoft.Office.Interop.Excel.ApplicationClass();
    Microsoft.Office.Interop.Excel.Workbook workbook = excel.Application.Workbooks.Add(true);

    int iCol = 0;
    foreach (DataColumn c in dt.Columns)
    {
        iCol++;
        excel.Cells[1, iCol] = c.ColumnName;
    }

    int iRow = 0;
    foreach (DataRow r in dt.Rows)
    {
        iRow++;

        // add each row's cell data...
        iCol = 0;
        foreach (DataColumn c in dt.Columns)
        {
             iCol++;
             excel.Cells[iRow + 1, iCol] = r[c.ColumnName];
        }
    }

    object missing = System.Reflection.Missing.Value;

    DateTime CurrentDate = DateTime.Now;          

    String CurDate = CurrentDate.ToShortDateString().Replace("/",".");

    workbook.SaveAs("ResourceProfile-" + CurDate + ".xls", Microsoft.Office.Interop.Excel.XlFileFormat.xlXMLSpreadsheet, missing, missing, false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);

    excel.Visible = true;
    Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)excel.ActiveSheet;
    ((Microsoft.Office.Interop.Excel._Worksheet)worksheet).Activate();

    ((Microsoft.Office.Interop.Excel._Application)excel).Quit();
}
只需向应用程序中添加一个,然后从用户处获取文件名:

String SaveName;

if saveFileDialog1.ShowDialog  = DialogResult.OK 
{
  SaveName := saveFileDialog1.FileName;
  workBook.SaveAs(SaveName, ...);
}
通过设置
SaveFileDialog
的各种属性,可以配置默认文件夹位置、文件扩展名和其他信息。您甚至可以将
SaveDialog.FileName
设置为您在
ShowDialog
之前创建的默认名称,以便他们接受或修改

您也可以使用
excel.Application.get\u FileDialog
执行此操作-以下是一个示例:

Microsoft.Office.Core.FileDialog fd = 
  excel.Application.get_FileDialog(Microsoft.Office.Core.MsoFileDialogType.msoFileDialogSaveAs);

fd.AllowMultiSelect = true; 
fd.Filters.Clear(); 
fd.Filters.Add("Excel Files", "*.xls;*.xlw", missing); 
fd.Filters.Add("All Files", "*.*", missing); 

if (fd.Show() != 0)
{
  fd.Execute();
}
如果处理大量记录(比如超过20000条或更多),那么执行“foreach”循环的方式将花费大量时间

我建议使用EPPlus lib

以下是如何将datatable直接放入excel:

worksheet.Cells["A1"].LoadFromDataTable(dtForExcel, true);
我已经测试过了,大约需要2秒


我不明白为什么MS没有在“Microsoft.Office.Interop.Excel”中提供这样的功能?使用下面提到的代码在aspx中显示“另存为”对话框

        var excel = new Microsoft.Office.Interop.Excel.Application();
        var workbook = excel.Workbooks.Add(true);
        // to add a sheet to workbook
        AddExcelSheet(dataTable1, workbook, "Sheet Name");

        string spreadsheetName = "DefaultFilename";
        excel.DisplayAlerts = false;
        Dialog saveAsDialog = excel.Dialogs[XlBuiltInDialog.xlDialogSaveAs];

        // to show dialog box with default filename
        saveAsDialog.Show(spreadsheetName);

        workbook.Close(true);
        excel.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);

谢谢Ken,我已经添加了SFD,现在当它到达“SFD.ShowDialog()”时,我收到了以下错误:在进行OLE调用之前,当前线程必须设置为单线程单元(STA)模式。确保主函数上标记了STAThreadAttribute。只有将调试器附加到进程时,才会引发此异常。它有什么作用吗?没有;代码通常工作正常。您是否在后台线程中进行处理?根据错误消息,您可以将
stathreadtribute
添加到
Main
函数中;这可能与调试器是运行应用程序的实际进程有关,因为它只在调试器下引发。对不起,我不知道这个问题的答案。我的第二个代码段(使用Excel自己的对话框)有什么变化吗?它与Ajax有什么关系吗?我正要研究你的另一个解决办法。恐怕我不知道(我不再使用Excel automation做很多工作;我通常使用Delphi,并且有一个第三方库,允许我在不运行Excel的情况下编写.xls文件(包括格式、公式、自动列大小调整等)。(事实上,Excel甚至不必安装。)第一个代码只是普通的SaveAsDialog代码,第二个代码是我快速查看后得到的。谢谢你,肯,一定有办法让第一个代码正常工作。我再给它半个小时,然后发布我的发现。
Microsoft.Office.Core.FileDialog fd = 
  excel.Application.get_FileDialog(Microsoft.Office.Core.MsoFileDialogType.msoFileDialogSaveAs);

fd.AllowMultiSelect = true; 
fd.Filters.Clear(); 
fd.Filters.Add("Excel Files", "*.xls;*.xlw", missing); 
fd.Filters.Add("All Files", "*.*", missing); 

if (fd.Show() != 0)
{
  fd.Execute();
}
worksheet.Cells["A1"].LoadFromDataTable(dtForExcel, true);
        var excel = new Microsoft.Office.Interop.Excel.Application();
        var workbook = excel.Workbooks.Add(true);
        // to add a sheet to workbook
        AddExcelSheet(dataTable1, workbook, "Sheet Name");

        string spreadsheetName = "DefaultFilename";
        excel.DisplayAlerts = false;
        Dialog saveAsDialog = excel.Dialogs[XlBuiltInDialog.xlDialogSaveAs];

        // to show dialog box with default filename
        saveAsDialog.Show(spreadsheetName);

        workbook.Close(true);
        excel.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);