0

こんにちは、jQuery と Microsoft ASP.net 2.0 を使用して Web 上でリッチ クライアント UI を開発しています。C# をサーバー側として使用しています。基本的に 2 つの問題があります。

  1. そのために、HTMLTextWriter および StringWriter クラス ライブラリを使用しています。私がインターネットで検索し、さまざまなチュートリアルやヒントから学んだことは、その場で Excel シートを生成する最も手頃な方法です。応答で作成された html を出力し、必要なヘッダーを設定してブラウザにどのような種類かを伝えるだけです。のデータが転送されており、その部分ではすべて正常に機能していますが、html を Excel スプレッドシートに変換する際に、ダウンロード ページの html マークアップを Excel マークアップにも追加します。
  2. データを出力した後に Response.Close() を呼び出すと、接続中止エラーが発生します。

これがコードスニペットです

public StringWriter getHTMLStream(){

            出力 = 新しい StringWriter();
            htmlWriter = 新しい HtmlTextWriter(出力);
            文字列 html= @"
      テーブル {mso-displayed-decimal-separator:'\.'; mso-displayed-thousand-separator:'\,';}.xlGeneral {padding-top:1px; パディング右:1px; パディング左:1px; mso-ignore:パディング; 色:ウィンドウテキスト; font-size:10.0pt; フォントの太さ:400; フォント スタイル:通常; テキスト装飾:なし; font-family:Arial; mso-generic-font-family:auto; mso-font-charset:0; mso-number-format:General; テキスト整列:一般; 垂直方向の位置合わせ:下; mso 背景ソース:自動; mso パターン:自動; 空白:nowrap;} ";
            html+=""+this.headerName+"-"+this.vehicleName+"";
            totalCols = (this.reportOrientation == "Horiz")?data.Columns.Count:2;
            if (this.reportOrientation == "水平")
            {
                html+="";
                // ヘッダー列を追加
                foreach (this.data.Columns の DataColumn colName)
                {
                    html+=""+colName.ColumnName.Trim()+"";
                }
                html+="";

                // ここでデータを追加します
                foreach (this.data.Rows の DataRow dr)
                {
                    html+="";
                    foreach (dr.ItemArray 内の文字列 colData)
                    {
                        html+=""+colData+"";
                    }
                    html+="";
                }
            }
            そうしないと
            {
                // 列を取得
                colsArr = 新しい文字列[this.data.Columns.Count];
                int colCounter = 0;
                foreach (this.data.Columns の DataColumn colName)
                {
                    colsArr[colCounter] = colName.ColumnName;
                    colCounter++;
                }
                //tableHeads = arrayToString(colsArr);
                // 行データを文字列配列で取得
                rowArr = 新しい文字列[this.data.Columns.Count];

                foreach (this.data.Rows の DataRow dr)
                {
                    colCounter = 0;
                    foreach (dr.ItemArray の文字列 col)
                    {
                        rowArr[colCounter] = col;
                        colCounter++;
                    }
                }
                //tableHeads = arrayToString(colsArr);
                // PDF 表のセルを追加
                for (int i = 0; i "+colsArr[i].Trim()+""+rowArr[i].Trim()+"";
                }

            }
            html+= "";
            htmlWriter.Write(html);
            出力を返します。
        }

        プライベート文字列 arrayToString(string[] array){
            string result = string.Join(",", array);
            結果 = 結果.Substring(0, 結果.長さ - 1);
            結果を返します。
        }
    }

そして、それが私がそれにアクセスする方法です

Response.Clear();
            createHTML speedXLS = new createHTML("Vehicle Speed Report", "Horiz", vehicleName, speedDT);
            Response.ContentType = "application/vnd.xls";
            Response.AddHeader("content-disposition", "attachment;filename=VSpeedReport-" + vehicleName + ".xls");
            Response.Write(speedXLS.getHTMLStream().ToString());
            //Response.Close();

そして、必要なxlsマークアップの横にあるダウンロードページのマークアップが私のExcelマークアップに追加されています。応答本文にページのマークアップを追加しないようにサーバーに指示するにはどうすればよいですか? **

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head><title>

    </title></head>
    <body>
        <form name="form1" method="post" action="downloadData.aspx?reportType=speed&amp;value=1&amp;valUnit=Miles&amp;reqType=XLS&amp;selVehicle=GTA02&amp;Email=gps%40gtalimo.com&amp;startDate=2012-4-27+23%3a21%3a00&amp;endDate=2012-4-28+01%3a21%3a00&amp;vehicleName=GTA+07" id="form1">
    <div>
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE2MTY2ODcyMjlkZKkkaxju0wAdoc1rGUJiLkzjS9eU" />
    </div>

        <div>

        </div>
        </form>
    </body>
    </html>

** コメントや提案をお願いします! ありがとう!

4

2 に答える 2

1

html テーブルを生成し、ブラウザーをだまして Excel で表示することは、データを Excel にエクスポートする最良の方法ではありません。これは解決策ではなくハックであり、IMO はいつこれが機能しなくなるか、おそらく次の Excel バージョンで、または何らかのウイルス/マルウェア対策/間違ったヘッダーでコンテンツを送信していることを検出したため、時間の問題であり、Excel 2007/2010 は既にユーザーに警告していますそのことについて。

**更新: ** 私の意見では、真の Excel ファイルを生成できるサードパーティの Excel ライブラリを使用すると、ブラウザで Excel が開き、コンテンツ ヘッダーが一致します。そして、本当に優れたオープン ソース ライブラリがあり、それらを使用すべきではない理由がまったくわかりません。

NPOI (xls) または / およびEPPlus (xlsx)

したがって、サードパーティのライブラリが CSV 形式を使用せずにそれを実行したい場合は、ここで DataTable を CSV にエクスポートする例を参照してください。

DataTable を CSV ストリームに変換する

代わりに、Excel スキーマを使用して XML にエクスポートすることもできます。コードは次のとおりです。

public static MemoryStream DataSetToExcelXml(DataSet ADataset)
{
  MemoryStream result = new MemoryStream();
  XmlDataDocument doc = new XmlDataDocument(ADataset);
  XslCompiledTransform trans = new XslCompiledTransform();
  XmlDocument xmlDoc = new XmlDocument();
  Stream shema = Assembly.GetExecutingAssembly().GetManifestResourceStream("ResPathToExcelSheet.xsl");
  xmlDoc.Load(shema);
  trans.Load(xmlDoc);
  trans.Transform(doc, null, result);
  return result;
}

スキーマ

<xsl:stylesheet version="1.0"
    xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:user="urn:my-scripts"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" >  
<xsl:template match="/">
  <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="http://www.w3.org/TR/REC-html40">
    <xsl:apply-templates/>
  </Workbook>
</xsl:template>
<xsl:template match="/*">
  <Worksheet>
  <xsl:attribute name="ss:Name">
  <xsl:value-of select="local-name(/*/*)"/>
  </xsl:attribute>
    <Table x:FullColumns="1" x:FullRows="1">
      <Row>
        <xsl:for-each select="*[position() = 1]/*">
          <Cell><Data ss:Type="String">
          <xsl:value-of select="local-name()"/>
          </Data></Cell>
        </xsl:for-each>
      </Row>
      <xsl:apply-templates/>
    </Table>
  </Worksheet>
</xsl:template>
<xsl:template match="/*/*">
  <Row>
    <xsl:apply-templates/>
  </Row>
</xsl:template>
<xsl:template match="/*/*/*">
  <Cell><Data ss:Type="String">
    <xsl:value-of select="."/>
  </Data></Cell>
</xsl:template>
</xsl:stylesheet>
于 2012-04-28T07:10:35.347 に答える
1

1.代わりに

       **strong text** Response.Clear();
createHTML speedXLS = new createHTML("Vehicle Speed Report", "Horiz", vehicleName, speedDT);
Response.ContentType = "application/vnd.xls";
Response.AddHeader("content-disposition", "attachment;filename=VSpeedReport-" + vehicleName + ".xls");
Response.Write(speedXLS.getHTMLStream().ToString());

使用する

 **Response.Buffer = true;**

   createHTML speedXLS = new createHTML("Vehicle Speed Report", "Horiz", vehicleName, speedDT);
        Response.ContentType = "application/vnd.xls";
        Response.AddHeader("content-disposition", "attachment;filename=VSpeedReport-" + vehicleName + ".xls");
        Response.Write(speedXLS.getHTMLStream().ToString());
  1. ストリーミング クラスを使用する場合は、"using" ステートメントを使用します。
于 2012-04-28T07:14:42.733 に答える