none
DataTableの内容をエクセルに保存する際にエラー発生 RRS feed

  • 質問

  • こんにちは。いつもお世話になっています。

    現在、C#(VS2005)でWebページを作成しています。

    DBにデータが格納されており、ページ上のボタンを押下すると、

    1.DBのデータをDataTableに格納

    2.DataTableの内容をエクセル形式で保存

    3.ファイルのダウンロードウィンドウを表示し、ページを表示しているPCに保存する

    というプログラムを作成しています。

    開発を行っている、PCのVS2005上では問題無く動作するのですが、

    「ビルド」→「Webサイトの発行」

    でサーバ上に配置し、クライアントPCでWebページを表示し、上記のボタンを押下すると

    -------------------------------------------------------------------------------------------------

    アプリケーションでサーバー エラーが発生しました。


    オブジェクト参照がオブジェクト インスタンスに設定されていません。

    説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。

    例外の詳細: System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。
    -------------------------------------------------------------------------------------------------

    のエラーが表示されます。

    ここ、数日いろいろと調べているのですが、お手上げ状態となってしまいました。

    サーバには、Office2003をインストールしてあり、「.NET プログラミング サポート」も

    インストールしてあります。

    エクセル保存のコードは下記サイトのコードを使用しています。

    http://architect360.apricot-jp.com/500tips/excel.html

    アドバイスをお願い致します。

     

    コードを記しておきます。

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    /// <summary>
    /// ExcelIF の概要の説明です
    /// </summary>
    public class ExcelIF
    {
     public ExcelIF()
     {
      //
      // TODO: コンストラクタ ロジックをここに追加します
      //
     }

     //エクセルシートにデータを書き出す行番号
     private const int ROW_OFFSET = 2;
     //(注意)Excelシートの行、列のインデックスは1から始まる
     //エクセルシートにデータを書き出す列番号
     private const int COLUMN_OFFSET = 1;

     ///<summary>
     /// データテーブルをエクセルファイルに出力します
     /// </summary>
     public bool CreateExcelFromDataTable(DataTable dt, string filePath, string sheetName)
     {
      //ヘッダー名称のリスト
      List<string> headers = new List<string>();

      foreach (System.Data.DataColumn col in dt.Columns)
      {
       headers.Add(col.ColumnName);
      }

      Microsoft.Office.Interop.Excel.Application xlsApplication = null;
      Microsoft.Office.Interop.Excel.Workbooks xlsBooks = null;
      Microsoft.Office.Interop.Excel.Workbook xlsBook = null;
      Microsoft.Office.Interop.Excel.Sheets xlsSheets = null;
      Microsoft.Office.Interop.Excel.Worksheet xlsSheet = null;
      Microsoft.Office.Interop.Excel.Range xlsRange = null;

      try
      {
       xlsApplication = new Microsoft.Office.Interop.Excel.Application();
       xlsApplication.DisplayAlerts = false;
       //保存時の確認ダイアログを表示しない

       xlsBooks = xlsApplication.Workbooks;
       xlsBook = xlsBooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
       xlsSheets = xlsBook.Worksheets;

       //(注意)シートのインデックスは1から始まる
       xlsSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlsSheets[1];
       xlsSheet.Name = sheetName;

       for (int i = 0; i <= headers.Count - 1; i++)
       {
        xlsRange = (Microsoft.Office.Interop.Excel.Range)xlsSheet.Cells[1, i + 1];
        xlsRange.Value2 = headers[i];
       }

       // セルに値を設定する。
       int sheetRowIndex = ROW_OFFSET;

       foreach (DataRow row in dt.Rows)
       {
        int sheetColumnIndex = COLUMN_OFFSET;

        foreach (DataColumn column in dt.Columns)
        {
         if (!row.IsNull(column))
         {
          xlsRange = (Microsoft.Office.Interop.Excel.Range)xlsSheet.Cells[sheetRowIndex, sheetColumnIndex];

          if (column.DataType.Name == "Integer" |
           column.DataType.Name == "Int32" |
           column.DataType.Name == "Decimal" |
           column.DataType.Name == "Long" |
           column.DataType.Name == "Double" |
           column.DataType.Name == "Short")
          {
           //セルの書式を数値型に設定
           xlsRange.NumberFormatLocal = "G/標準";
          }
          else if (column.DataType.Name == "DateTime")
          {
           xlsRange.NumberFormatLocal = "yyyy/m/d h:mm";
          }
          else
          {
           //セルの書式を文字列型に設定
           xlsRange.NumberFormatLocal = "@";
          }

          xlsRange.Value2 = row[column];
          xlsRange.Columns.AutoFit();
          ReleaseComObject((object)xlsRange);
          sheetColumnIndex += 1;
         }
        }
        sheetRowIndex += 1;
       }

       // 保存
       xlsBook.SaveAs(filePath, Microsoft.Office.Interop.Excel.XlFileFormat.xlXMLSpreadsheet, null, null, null, null, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, null, null, null, null, null);

       return true;
      }

      catch (Exception ex)
      {
       return false;
      }
      finally
      {
       // エクセル関係のオブジェクトは必ず解放すること
       ReleaseComObject((object)xlsRange);
       ReleaseComObject((object)xlsSheet);
       ReleaseComObject((object)xlsSheets);
       xlsBook.Close(true, filePath, false);
       ReleaseComObject((object)xlsBook);
       ReleaseComObject((object)xlsBooks);
       xlsApplication.Quit();
       ReleaseComObject((object)xlsApplication);
      }
     }

     /// <summary>
     /// COMオブジェクトを開放します。
     /// </summary>
     private static void ReleaseComObject(object target)
     {
      try
      {
       if ((target != null))
       {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(target);
       }
      }
      finally
      {
       target = null;
      }
     }
    }

    2010年8月19日 5:30

回答

  • KB257757 を読んでおくことをお勧めします。

    マイクロソフトは、現在のところ、無人の非対話型クライアント アプリケーションまたはコンポーネント (ASP、ASP.NET、DCOM、および NT サービスを含む) からの Microsoft Office アプリケーションのオートメーションに関して、推奨もサポートも行っていません。
    • 回答の候補に設定 山本春海 2010年8月25日 7:42
    • 回答としてマーク 山本春海 2010年9月1日 8:33
    2010年8月19日 7:13

すべての返信

  • 念のためにお聞きしますが、実行権限はどうなっていますか?

    下記のサイトを一度ご覧ください。

    ASP.NETからのExcel起動について
    http://social.msdn.microsoft.com/Forums/ja-JP/vbgeneralja/thread/658f824d-7511-44ee-8fcb-84449025bc2a

    2010年8月19日 5:57
  • KB257757 を読んでおくことをお勧めします。

    マイクロソフトは、現在のところ、無人の非対話型クライアント アプリケーションまたはコンポーネント (ASP、ASP.NET、DCOM、および NT サービスを含む) からの Microsoft Office アプリケーションのオートメーションに関して、推奨もサポートも行っていません。
    • 回答の候補に設定 山本春海 2010年8月25日 7:42
    • 回答としてマーク 山本春海 2010年9月1日 8:33
    2010年8月19日 7:13
  • 返信ありがとうございます。

    お教え頂いたページの確認・設定を行いました。

    --------------------------------------------------------------------------------------------------------

    aspnet_wp.exeの実行ユーザ:ASPNET

    web.configの<system.web>以下に<identity impersonate="true"/>を追加:状況変わらず

    DCOMCNFGの[コンソールルート]→[コンポーネントサービス]→[コンピュータ]→[マイコンピュータ]→

    右クリック→プロパティ→[COMセキュリティ]タブ

    「アクセス許可」の「既定値の編集」でASPNETユーザを追加

    「起動とアクティブ化のアクセス許可」の「既定値の編集」でASPNETユーザを追加

    --------------------------------------------------------------------------------------------------------

    上記の事を行いましたが、状況は変わりませんでした。

    何か間違っている箇所があれば、ご指摘をお願い致します。

    2010年8月19日 7:21
  • Excelの実行権限やファイルやフォルダへのアクセス権も確認なさっていますでしょうか?

    #開発環境では、管理者権限を持っているユーザで起動するようにしていませんか?

     

    2010年8月19日 7:30
  • Excel で開ければいいのなら、こんな方法もあります。

    http://codezine.jp/article/detail/194


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答の候補に設定 山本春海 2010年9月1日 8:33
    2010年8月19日 8:52
  • なかむらさん。

    返信ありがとうございます。

    なるほど!こんな手もあるんですね~。

    参考にさせて頂きますm(__)m

     

    2010年8月19日 8:59
  • 今回の問題の根本的な解決にはなっていませんが、

    下記のアドレスのようにするとエラーは発生しませんでした。

    http://blog.so-net.ne.jp/jem/2009-03-07

     

    • 回答の候補に設定 山本春海 2010年9月1日 8:33
    2010年8月19日 9:00