- PR -

DataGridのデータをexcelのcsv形式で出力したい

1
投稿者投稿内容
kozutsumi
会議室デビュー日: 2003/03/11
投稿数: 8
投稿日時: 2003-03-17 13:18
いつも参考にさせていただいています。

VBでwebフォームを作成し、
Webフォーム上のDataGridのデータをexcelのカンマ区切りのcsv形式で出力したいのですが、
そこで悩んでいます。

過去のスレッドをいろいろ見させていただき、
件名:【ASP.NET】DataGrid→Excel形式への変換
を参考にしたのですが、
この方法だと、
webページとして表示/保存されてしまいます。

DataGridのデータを通常のcsvの形式に変換させる方法をご存知の方がいらっしゃいましたら
ぜひ教えてください。
よろしくお願いいたします。

下記にコーディングサンプルを記述します
--------------------------------------------------------------
Private Sub btnExp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExp.Click

Dim strFilename As String = "test"

Response.Clear()
Response.ContentType = "application/vnd.ms-excel"
Response.Charset = ""
Me.EnableViewState = False
Dim tw As New System.IO.StringWriter()
Dim hw As New System.Web.UI.HtmlTextWriter(tw)
dgHYOKA.RenderControl(hw)

Response.AppendHeader("Content-Disposition", "attachment; filename=" & strFilename & ".csv")
Response.Write(tw.ToString())
Response.End()

End Sub
--------------------------------------------------------------
kozutsumi
会議室デビュー日: 2003/03/11
投稿数: 8
投稿日時: 2003-03-17 13:52
すみません。追記です。

DataGridのデータをExcelにはきだすのに、DataGridのRenderControl()メソッドを
使用せず、地道にloopでまわしてカンマ区切りの文字列を作成する方法も考えたのですが
今度はDataGridのheaderデータの取得方法がわかりません。

DataGridのデータを通常のcsvの形式に変換できれば、こちらの方法でも
かまいませんので、
DataGridのheaderデータを取得する方法をご存知の方がいらっしゃいましたら
ぜひ教えてください。
よろしくお願いいたします。

下記にサンプルを記述します(csvファイルにタイトルが表示できない)
--------------------------------------------------------------
Private Sub btnExp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExp.Click

Dim strFilename As String = "test"

Response.ContentType = "application/vnd.ms-excel"
Response.AppendHeader("Content-Disposition", "attachment; filename=" & strFilename & ".csv")
Dim headerToList As System.Web.UI.WebControls.TableHeaderCell
Dim rowToList As System.Web.UI.WebControls.DataGridItem
Dim cellToList As System.Web.UI.WebControls.TableCell
Dim strRow As String
For Each rowToList In dgHYOKA.Items
strRow = ""
For Each cellToList In rowToList.Cells
If strRow <> "" Then
strRow = strRow & ","
End If
strRow = strRow & cellToList.Text
Next cellToList
Response.Write(strRow & vbNewLine)
Next rowToList
Response.End()

End Sub
--------------------------------------------------------------

なぬらに
会議室デビュー日: 2003/02/28
投稿数: 9
投稿日時: 2003-03-17 16:40
はじめまして なぬと申します

ヘッダーのテキストは
DataGridItemではなく
DataGridColumnのHeaderTextプロパティになります。

ちなみに私もcsvファイル作成のときは地道に回しました。
これは余談になりますが、文字列の代入演算を反復する場合は
StringBuilderを使用するとレスポンスが向上します。

以上それでは、よろしくお願いします。
kozutsumi
会議室デビュー日: 2003/03/11
投稿数: 8
投稿日時: 2003-03-17 17:48
ご返答有難うございます。

下記のように書き直してみたのですが、
一番外側のloopを一度も通らずに抜けてしまいます。

--------------------------------------------------------------
Private Sub btnExp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExp.Click

Response.Clear()
Response.ContentEncoding = System.Text.Encoding.GetEncoding("shift-jis")
Response.ContentType = "application/vnd.ms-excel"
Response.AppendHeader("Content-Disposition", "attachment; filename=" & strFilename & ".csv")

Dim rowToList As System.Web.UI.WebControls.DataGridColumn
Dim cellToList
Dim strRow As String

For Each rowToList In dgHYOKA.Columns
strRow = ""
For Each cellToList In rowToList.HeaderText
If strRow <> "" Then
strRow = strRow & ","
End If
strRow = strRow & cellToList.Text
Next cellToList
Response.Write(strRow & vbNewLine)
Next rowToList

Response.End()

End Sub
--------------------------------------------------------------

ためしに
--------------------------------------------------------------
Dim test = dgHYOKA.Columns(0).HeaderText
--------------------------------------------------------------
としてみたところ、下記エラーになってしまいます。
「インデックスが範囲を超えています。負でない値で、コレクションのサイズ
よりも小さくなければなりません。パラメータ名 : index 」

使い方が根本的に間違っているのでしょうか?
申し訳ありませんが、もう少し教えていただけますでしょうか。
よろしくお願いいたします。
なぬらに
会議室デビュー日: 2003/02/28
投稿数: 9
投稿日時: 2003-03-18 10:03
お世話様です。再びなぬです。

ヘッダー用と内容用に2段階に分けます。
DataGridColumnは列を定義するものであって列の内容の参照はできません。
列の内容の参照は
DataGrid.Items(x).Cells(y).Textでx行y列目の内容を参照します。

面倒くさいですよね。

コード:
Dim colToList As System.Web.UI.WebControls.DataGridColumn
'LOOP FOR DataGridColumns 方向イメージ→
For Each colToList In dgHYOKA.Columns 
 strRow = "" 
 If strRow <> "" Then 
  strRow = strRow & "," 
 End If
 'ヘッダーテキスト
 strRow = strRow & colToList.HeaderText
 Response.Write(strRow & vbNewLine) 
Next colToList

Dim rowToList As System.Web.UI.WebControls.DataGridItem 
Dim cellToList As System.Web.UI.WebControls.TableCell 
'LOOP FOR DataGridItem 方向イメージ↓
For Each rowToList In dgHYOKA.Items 
 strRow = ""
 'LOOP FOR TableCell 方向イメージ→
 For Each cellToList In rowToList.Cells 
  If strRow <> "" Then
   strRow = strRow & "," 
  End If 
  strRow = strRow & cellToList.Text 
 Next cellToList 
 Response.Write(strRow & vbNewLine) 
Next rowToList


自動生成カラムの場合
DataGrid.Columnsでは取りかたを知らないので
個々のDataGridに予めカラムを追加して
ヘッダーを定義しておく必要があるでしょう。

以上よろしくお願いします。
kozutsumi
会議室デビュー日: 2003/03/11
投稿数: 8
投稿日時: 2003-03-18 19:05
とても丁寧なご返答有難うございます。

おかげさまで実現することが出来ました。
が、かなり強引なやり方になってしまいました。

DataGridのColumnが取得できなかった理由は
投げるSQLにより表示する列が変動するためにDataGridを動的に作成していて
DataGridのColumn定義がなかったからのようです。

そこで
ItemDataBoundでDataGridのColumnを追加し、HeaderTextを定義してみたのですが
excel表示させるためのボタンを押すとPostbackが発生し、
せっかく定義したColumnが消えてしまうようなのです。

結局、タイトル部分のカンマ区切りの文字列をItemDataBoundで組み立て、
ViewStateに格納することにしてしまいました。

一応実現できたので今のところこのままにしていますが、
もっとよいコーディング方法はありますでしょうか?

コード:
   Private Sub dgHYOKA_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgHYOKA.ItemDataBound

        Dim i As Integer
        Select Case e.Item.ItemType
            Case ListItemType.Header                                'ヘッダー

                'HeaderText設定(←Postback時消えてしまう)
                'For i = 0 To e.Item.Cells.Count - 1
                '    Dim AddColumn As New BoundColumn()
                '    AddColumn.HeaderText = e.Item.Cells(i).Text
                '    dgHYOKA.Columns.AddAt(i, AddColumn)
                'Next i

                'csv出力用文字列作成
                Dim strToExlTitle As String = ""
                For i = 0 To e.Item.Cells.Count - 1
                    If strToExlTitle <> "" Then
                        strToExlTitle &= ","
                    End If
                    strToExlTitle &= e.Item.Cells(i).Text
                Next i
                ViewState("ToExlTitle") = strToExlTitle
        End Select

    End Sub



コード:
    Private Sub btnExp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExp.Click

        Dim strFilename As String = "test"

        Response.Clear()
        Response.ContentEncoding = System.Text.Encoding.GetEncoding("shift-jis")
        Response.ContentType = "application/vnd.ms-excel"
        Response.AppendHeader("Content-Disposition", "attachment; filename=" & strFilename & ".csv")

        Dim headerToList As System.Web.UI.WebControls.TableHeaderCell
        Dim rowToList As System.Web.UI.WebControls.DataGridItem
        Dim cellToList As System.Web.UI.WebControls.TableCell

        'タイトル
        Response.Write(CType(ViewState("ToExlTitle"), String) & vbNewLine)

        'データ
        For Each rowToList In dgHYOKA.Items
            Dim strRow As New System.Text.StringBuilder()
            For Each cellToList In rowToList.Cells
                If strRow.Length <> 0 Then
                    strRow.Append(",")
                End If
                If cellToList.Text = " " Then
                    cellToList.Text = ""
                End If
                strRow.Append(cellToList.Text)
            Next cellToList
            Response.Write(strRow.ToString & vbNewLine)
        Next rowToList

        Response.End()


damepg
大ベテラン
会議室デビュー日: 2003/03/19
投稿数: 229
お住まい・勤務地: 東京都内
投稿日時: 2003-06-02 23:49
引用:

なぬさんの書き込み (2003-03-18 10:03) より:
お世話様です。再びなぬです。

ヘッダー用と内容用に2段階に分けます。
DataGridColumnは列を定義するものであって列の内容の参照はできません。
列の内容の参照は
DataGrid.Items(x).Cells(y).Textでx行y列目の内容を参照します。

面倒くさいですよね。

<!-- BBCode Start --><TABLE BORDER="0" ALIGN="CENTER" WIDTH="90%" CELLSPACING="0" CELLPADDING="0"><TR><TD WIDTH="5%" NOWRAP><FONT SIZE="-1">コード:</FONT></TD><TD WIDTH="95%"><HR SIZE="1" WIDTH="100%"></TD></TR><TR><TD COLSPAN="2"><PRE>Dim colToList As System.Web.UI.WebControls.DataGridColumn
'LOOP FOR DataGridColumns 方向イメージ→
For Each colToList In dgHYOKA.Columns
 strRow = ""
 If strRow <> "" Then
  strRow = strRow & ","
 End If
 'ヘッダーテキスト
 strRow = strRow & colToList.HeaderText
 Response.Write(strRow & vbNewLine)
Next colToList

Dim rowToList As System.Web.UI.WebControls.DataGridItem
Dim cellToList As System.Web.UI.WebControls.TableCell
'LOOP FOR DataGridItem 方向イメージ↓
For Each rowToList In dgHYOKA.Items
 strRow = ""
 'LOOP FOR TableCell 方向イメージ→
 For Each cellToList In rowToList.Cells
  If strRow <> "" Then
   strRow = strRow & ","
  End If
  strRow = strRow & cellToList.Text
 Next cellToList
 Response.Write(strRow & vbNewLine)
Next rowToList</PRE><HR SIZE="1" WIDTH="100%"></TD></TR></TABLE><!-- BBCode End -->
自動生成カラムの場合
DataGrid.Columnsでは取りかたを知らないので
個々のDataGridに予めカラムを追加して
ヘッダーを定義しておく必要があるでしょう。

以上よろしくお願いします。

1

スキルアップ/キャリアアップ(JOB@IT)