web-dev-qa-db-ja.com

c#(WinForms-App)DataSetをExcelにエクスポート

ASPコードなしでデータセットをExcelファイルにエクスポートするソリューション(HttpResonpsne ...)が必要ですが、これを行うための良い例が見つかりません...

よろしくお願いします

24
maveonair

DataGridViewまたはDataTableをExcelファイルにエクスポートするクラスを作成しました。少し変更して、代わりにDataSetを使用することができます(その中のDataTablesを繰り返す)。また、拡張できる基本的な書式設定も行います。

使用するには、ExcelExportを呼び出し、ファイル名と、エクスポート後にファイルを自動的に開くかどうかを指定します。拡張メソッドを作成することもできましたが、作成しませんでした。お気軽に。

Excelファイルは栄光のXMLドキュメントとして保存でき、これはそれを利用することに注意してください。

編集:これはバニラStreamWriterを使用するために使用されましたが、指摘されているように、多くの場合、物事は正しくエスケープされません。これでXmlWriterが使用され、エスケープが行われます。

ExcelWriterクラスはXmlWriterをラップします。気にしていませんが、行を開始する前にセルデータを書き込めないことを確認するために、もう少しエラーチェックを行うことをお勧めします。コードは以下のとおりです。

public class ExcelWriter : IDisposable
{
    private XmlWriter _writer;

    public enum CellStyle { General, Number, Currency, DateTime, ShortDate };

    public void WriteStartDocument()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteProcessingInstruction("mso-application", "progid=\"Excel.Sheet\"");
        _writer.WriteStartElement("ss", "Workbook", "urn:schemas-Microsoft-com:office:spreadsheet");
         WriteExcelStyles();
   }

    public void WriteEndDocument()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
    }

    private void WriteExcelStyleElement(CellStyle style)
    {
        _writer.WriteStartElement("Style", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("ID", "urn:schemas-Microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteEndElement();
    }

    private void WriteExcelStyleElement(CellStyle style, string NumberFormat)
    {
        _writer.WriteStartElement("Style", "urn:schemas-Microsoft-com:office:spreadsheet");

        _writer.WriteAttributeString("ID", "urn:schemas-Microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteStartElement("NumberFormat", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Format", "urn:schemas-Microsoft-com:office:spreadsheet", NumberFormat);
        _writer.WriteEndElement();

        _writer.WriteEndElement();

    }

    private void WriteExcelStyles()
    {
        _writer.WriteStartElement("Styles", "urn:schemas-Microsoft-com:office:spreadsheet");

        WriteExcelStyleElement(CellStyle.General);
        WriteExcelStyleElement(CellStyle.Number, "General Number");
        WriteExcelStyleElement(CellStyle.DateTime, "General Date");
        WriteExcelStyleElement(CellStyle.Currency, "Currency");
        WriteExcelStyleElement(CellStyle.ShortDate, "Short Date");

        _writer.WriteEndElement();
    }

    public void WriteStartWorksheet(string name)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Worksheet", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Name", "urn:schemas-Microsoft-com:office:spreadsheet", name);
        _writer.WriteStartElement("Table", "urn:schemas-Microsoft-com:office:spreadsheet");
    }

    public void WriteEndWorksheet()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public ExcelWriter(string outputFileName)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        _writer = XmlWriter.Create(outputFileName, settings);
    }

    public void Close()
    {
        if (_writer == null) throw new InvalidOperationException("Already closed.");

        _writer.Close();
        _writer = null;
    }

    public void WriteExcelColumnDefinition(int columnWidth)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Column", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteStartAttribute("Width", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteValue(columnWidth);
        _writer.WriteEndAttribute();
        _writer.WriteEndElement();
    }

    public void WriteExcelUnstyledCell(string value)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Cell", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteStartElement("Data", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("Type", "urn:schemas-Microsoft-com:office:spreadsheet", "String");
        _writer.WriteValue(value);
        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public void WriteStartRow()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Row", "urn:schemas-Microsoft-com:office:spreadsheet");
    }

    public void WriteEndRow()
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteEndElement();
    }

    public void WriteExcelStyledCell(object value, CellStyle style)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        _writer.WriteStartElement("Cell", "urn:schemas-Microsoft-com:office:spreadsheet");
        _writer.WriteAttributeString("StyleID", "urn:schemas-Microsoft-com:office:spreadsheet", style.ToString());
        _writer.WriteStartElement("Data", "urn:schemas-Microsoft-com:office:spreadsheet");
        switch (style)
        {
            case CellStyle.General:
                _writer.WriteAttributeString("Type", "urn:schemas-Microsoft-com:office:spreadsheet", "String");
                break;
            case CellStyle.Number:
            case CellStyle.Currency:
                _writer.WriteAttributeString("Type", "urn:schemas-Microsoft-com:office:spreadsheet", "Number");
                break;
            case CellStyle.ShortDate:
            case CellStyle.DateTime:
                _writer.WriteAttributeString("Type", "urn:schemas-Microsoft-com:office:spreadsheet", "DateTime");
                break;
        }
        _writer.WriteValue(value);
        //  tag += String.Format("{1}\"><ss:Data ss:Type=\"DateTime\">{0:yyyy\\-MM\\-dd\\THH\\:mm\\:ss\\.fff}</ss:Data>", value,

        _writer.WriteEndElement();
        _writer.WriteEndElement();
    }

    public void WriteExcelAutoStyledCell(object value)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");

        //write the <ss:Cell> and <ss:Data> tags for something
        if (value is Int16 || value is Int32 || value is Int64 || value is SByte ||
            value is UInt16 || value is UInt32 || value is UInt64 || value is Byte)
        {
            WriteExcelStyledCell(value, CellStyle.Number);
        }
        else if (value is Single || value is Double || value is Decimal) //we'll assume it's a currency
        {
            WriteExcelStyledCell(value, CellStyle.Currency);
        }
        else if (value is DateTime)
        {
            //check if there's no time information and use the appropriate style
            WriteExcelStyledCell(value, ((DateTime)value).TimeOfDay.CompareTo(new TimeSpan(0, 0, 0, 0, 0)) == 0 ? CellStyle.ShortDate : CellStyle.DateTime);
        }
        else
        {
            WriteExcelStyledCell(value, CellStyle.General);
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        if (_writer == null)
            return;

        _writer.Close();
        _writer = null;
    }

    #endregion
}

次に、以下を使用してDataTableをエクスポートできます。

public static void ExcelExport(DataTable data, String fileName, bool openAfter)
{
    //export a DataTable to Excel
    DialogResult retry = DialogResult.Retry;

    while (retry == DialogResult.Retry)
    {
        try
        {
            using (ExcelWriter writer = new ExcelWriter(fileName))
            {
                writer.WriteStartDocument();

                // Write the worksheet contents
                writer.WriteStartWorksheet("Sheet1");

                //Write header row
                writer.WriteStartRow();
                foreach (DataColumn col in data.Columns)
                    writer.WriteExcelUnstyledCell(col.Caption);
                writer.WriteEndRow();

                //write data
                foreach (DataRow row in data.Rows)
                {
                    writer.WriteStartRow();
                    foreach (object o in row.ItemArray)
                    {
                        writer.WriteExcelAutoStyledCell(o);
                    }
                    writer.WriteEndRow();
                }

                // Close up the document
                writer.WriteEndWorksheet();
                writer.WriteEndDocument();
                writer.Close();
                if (openAfter)
                    OpenFile(fileName);
                retry = DialogResult.Cancel;
            }
        }
        catch (Exception myException)
        {
            retry = MessageBox.Show(myException.Message, "Excel Export", MessageBoxButtons.RetryCancel, MessageBoxIcon.Asterisk);
        }
    }
}
36
lc.

次のサイトは、DataSet(またはDataTableまたはList <>)を「genuine」Excel 2007 .xlsxファイルにエクスポートする方法を示しています。

OpenXMLライブラリを使用するため、サーバーにExcelをインストールする必要はありません。

C#ExportToExcelライブラリ

すべてのソースコードが無料で提供されますとともに、ASP.NET、ASP.NET Core 2+、または通常のC#でそれを使用する手順が提供されます。

自分のアプリケーションに追加するのはとっても簡単です。1つの関数を呼び出し、Excelファイル名とデータソースを渡すだけです。

DataSet ds = CreateSampleData();
string excelFilename = "C:\\Sample.xlsx";
CreateExcelFile.CreateExcelDocument(ds, excelFilename);

お役に立てれば。

3
Mike Gledhill

私はこれをコメントに追加したでしょうが、私はスタックするのが初めてなので、コメントできません。 lcのソリューションを使用して、無効なXML文字がないか文字列文字をテストする別の関数を追加しました。ときどきExcelにエクスポートしていたときに、エクスポートが失敗する原因となっている文字が見つかりました。

Lcのコードにある関数の1つを変更する必要があります。

public void WriteExcelAutoStyledCell(object value)
    {
        if (_writer == null) throw new InvalidOperationException("Cannot write after closing.");
        string newValue = string.Empty;

        try
        {
            //write the <ss:Cell> and <ss:Data> tags for something
            if (value is Int16 || value is Int32 || value is Int64 || value is SByte ||
                value is UInt16 || value is UInt32 || value is UInt64 || value is Byte)
            {
                WriteExcelStyledCell(value, CellStyle.Number);
            }
            else if (value is Single || value is Double || value is Decimal) //we'll assume it's a currency
            {
                WriteExcelStyledCell(value, CellStyle.Currency);
            }
            else if (value is DateTime)
            {
                //check if there's no time information and use the appropriate style
                WriteExcelStyledCell(value, ((DateTime)value).TimeOfDay.CompareTo(new TimeSpan(0, 0, 0, 0, 0)) == 0 ? CellStyle.ShortDate : CellStyle.DateTime);
            }
            else
            {
                newValue = CheckXmlCompatibleValues(value.ToString()).ToString();
                WriteExcelStyledCell(newValue, CellStyle.General);
            }
        }
        catch (Exception thisException)
        {
            throw new InvalidOperationException(thisException.Message.ToString());
        }
    }

そして、この関数を「ExcelWriter」クラスに追加します

public string CheckXmlCompatibleValues(string value)
    {
        string newValue = string.Empty;
        bool found = false;

        foreach (char c in value)
        {
            if (XmlConvert.IsXmlChar(c))
                newValue += c.ToString();
            else
                found = true;
        }

        return newValue.ToString();
    }

lc。コードをありがとう!

1
lwsolutions

コードにはnull値に関する問題があります。

 public void WriteExcelAutoStyledCell(object value)
    {
        //solve null values
        if (value is DBNull) return;
1
user2882267

これは本当に役立つトップ回答の投稿でしたが、XMLファイルをデータテーブルにインポートする簡単な方法がなかったため、欠けていることがわかりました。私は自分で書く必要があり、他の誰かが同じボートに乗っている場合に備えて、ここでそれを共有すると思いました(Googleはその点で非常に役に立ちませんでした)。

public static DataTable ImportExcelXML(string Filename)
    {
        //create a new dataset to load in the XML file
        DataSet DS = new DataSet();
        //Read the XML file into the dataset
        DS.ReadXml(Filename);
        //Create a new datatable to store the raw Data
        DataTable Raw = new DataTable();
        //assign the raw data from the file to the datatable
        Raw = DS.Tables["Data"];
        //count the number of columns in the XML file
        int ColumnNumber = Raw.Columns.Count;
        //create a datatable to store formatted Import Data
        DataTable ImportData = new DataTable();
        //create a string list to store the cell data of each row
        List<string> RowData = new List<string>();
        //loop through each row in the raw data table
        for (int Counter = 0; Counter < Raw.Rows.Count; Counter++)
        {
            //if the data in the row is a colum header
            if (Counter < ColumnNumber)
            {
                //add the column name to our formatted datatable
                ImportData.Columns.Add(Raw.Rows[Counter].ItemArray.GetValue(1).ToString());
            }
            else
            {
                //if the row # (1 row = 1 cell from the Excel file) from the raw datatable is divisable evenly by the number of columns in the formated import datatable AND this is not the 1st row of the raw table data after the headers
                if ((Counter % ColumnNumber == 0) && (Counter != ColumnNumber))
                {
                    //add the row we just built to the formatted import datatable
                    ImportData.Rows.Add(GenerateRow(ImportData, RowData));
                    //clear rowdata list in preperation for the next row
                    RowData.Clear();
                }
                //add the current cell data value from the raw datatable to the string list of cell values for the next row to be added to the formatted input datatable
                RowData.Add(Raw.Rows[Counter].ItemArray.GetValue(1).ToString());
            }
        }
        //add the final row
        ImportData.Rows.Add(GenerateRow(ImportData, RowData));

        return ImportData;
    }

    public static DataRow GenerateRow(DataTable ImportData, List<string> RowData)
    {
        //create a counter to keep track of the column position during row composition
        int ColumnPosition = 0;
        //make a new datarow based on the schema of the formated import datatable
        DataRow NewRow = ImportData.NewRow();
        //for each string cell value collected for the RowData list for this row
        foreach (string CellData in RowData)
        {
            //add the cell value to the new datarow
            NewRow[ImportData.Columns[ColumnPosition].ColumnName] = CellData;
            //incriment column position in the new row
            ColumnPosition++;
        }
        //return the generated row
        return NewRow;
    }
1
Adamantine

.NETアプリケーションでExcelファイルを作成することは非常に一般的であり、以前に同様の質問が数回行われています。たとえば here および here です。最後の質問ではExcelファイルの読み取りについて質問しますが、提案されているほとんどの解決策は両方の方法で機能するはずです。

1
Rune Grimstad
using XL = Microsoft.Office.Interop.Excel;
using System.Reflection;

public static void Datasource(DataTable dt)
{
    XL.Application oXL;
    XL._Workbook oWB;
    XL._Worksheet oSheet;
    XL.Range oRng;

    try
    {
        oXL = new XL.Application();
        Application.DoEvents();
        oXL.Visible = false;

        //Get a new workbook.
        oWB = (XL._Workbook)(oXL.Workbooks.Add(Missing.Value));
        oSheet = (XL._Worksheet)oWB.ActiveSheet;

        //System.Data.DataTable dtGridData=ds.Tables[0];

        int iRow = 2;
        if (dt.Rows.Count > 0)
        {
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                oSheet.Cells[1, j + 1] = dt.Columns[j].ColumnName;
            }

            // For each row, print the values of each column.
            for (int rowNo = 0; rowNo < dt.Rows.Count; rowNo++)
            {
                for (int colNo = 0; colNo < dt.Columns.Count; colNo++)
                {
                    oSheet.Cells[iRow, colNo + 1] = dt.Rows[rowNo][colNo].ToString();
                }
                iRow++;
            }
            iRow++;
        }
        oRng = oSheet.get_Range("A1", "IV1");
        oRng.EntireColumn.AutoFit();
        oXL.Visible = true;
    }
    catch (Exception theException)
    {
        throw theException;
    }
    finally
    {
        oXL = null;
        oWB = null;
        oSheet = null;
        oRng = null;
    }
}

Excelからデータテーブルにインポート:

 DataTable dtTable = new DataTable();
 DataColumn col = new DataColumn("Rfid");
 dtTable.Columns.Add(col);
 DataRow drRow;

 Microsoft.Office.Interop.Excel.Application ExcelObj =
        new Microsoft.Office.Interop.Excel.Application();
 Microsoft.Office.Interop.Excel.Workbook theWorkbook =
            ExcelObj.Workbooks.Open(txt_FilePath.Text, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
 Microsoft.Office.Interop.Excel.Sheets sheets = theWorkbook.Worksheets;
 try
 {
     for (int sht = 1; sht <= sheets.Count; sht++)
     {
          Microsoft.Office.Interop.Excel.Worksheet worksheet =
                    (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(sht);

          for (int i = 2; i <= worksheet.UsedRange.Rows.Count; i++)
          {
              Microsoft.Office.Interop.Excel.Range range = worksheet.get_Range("A" + i.ToString(), "B" + i.ToString());
              System.Array myvalues = (System.Array)range.Cells.Value2;
              String name = Convert.ToString(myvalues.GetValue(1, 1));
              if (string.IsNullOrEmpty(name) == false)
              {
                  drRow = dtTable.NewRow();
                  drRow["Rfid"] = name;
                  dtTable.Rows.Add(drRow);
              }
          }
              Marshal.ReleaseComObject(worksheet);
              worksheet = null;
        }
    return dtTable;
}
catch
{
    throw;
}
finally
{
   // Marshal.ReleaseComObject(worksheet);
    Marshal.ReleaseComObject(sheets);
    Marshal.ReleaseComObject(theWorkbook);
    Marshal.ReleaseComObject(ExcelObj);
    //worksheet = null;
    sheets = null;
    theWorkbook = null;
    ExcelObj = null;
}
1
user1314323

Microsoftには、Excelファイルをインポート/エクスポートするための組み込みのソリューションがあります。これは最も単純なライブラリではありませんが、一般に、上記にリストされた他のライブラリよりもうまく機能します。

これを行うために必要なライブラリはOfficeに含まれており、Microsoft.Office.Interop.ExcelのFrameworkアセンブリのリストの下にあります。

ここにいくつかのサンプルコードがあります:

using Excel = Microsoft.Office.Interop.Excel;

Excel.Application app = new Excel.Application();

//Open existing workbook
//Excel.Workbook workbook = xlApp.Workbooks.Open(fileName);

//Create new workbook
Excel.Workbook workbook = app.Workbooks.Add();

Excel.Worksheet worksheet = workbook.ActiveSheet;

worksheet.Cells[1,1] = "Hello world!"; // Indexes start at 1, because Excel
workbook.SaveAs("C:\\MyWorkbook.xlsx");
workbook.Close();
app.Quit();
0
DamienMann