0

私の仕事はAccessデータベースを取得してExcelファイルを作成することですが、 OleDbが使用するExcelファイルを作成できないようです。

Excelファイル名は、ツールを実行しているエンジニアによって提供されます。Accessデータベースの各データテーブルは、Excelファイルのワークシートになります。

今のところ、乗り越えられないハードルが1つあります。Excelファイルが存在しないと、作成できません。

internal const string XL_FMT = "Provider=Microsoft.{0}.OLEDB.{1};Data Source={2};Mode=ReadWrite;Extended Properties=\"Excel {1};HDR={3};IMEX=1;\"";
internal DataTable tableNames;
internal OleDbConnection oleCon;
private string conStr;

public OleBase(string connectionString) {
  conStr = connectionString;
  // Using the debugger, conStr is:
  // "Provider=Microsoft.ACE.OLEDB.12.0;" +
  // "Data Source=C:\\Users\\cp-jpool\\Documents\\Ecat5.xlsx;" +
  // "Mode=ReadWrite;Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1;\""
  object[] param = new object[] { null, null, null, "TABLE" };
  oleCon = new OleDbConnection(conStr);
  oleCon.Open();
  tableNames = oleCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, param);
}

Excelファイルが存在しない場合、呼び出すたびにOpen()次のOleDbExceptionが発生します。

" MicrosoftAccessデータベースエンジンはオブジェクト'C:\ Users \ cp-jpool \ Documents \ Ecat5.xlsx'を見つけることができませんでした。オブジェクトが存在し、その名前とパス名を正しく入力していることを確認してください。' C:\の場合Users \ cp-jpool \ Documents \ Ecat5.xlsx'はローカルオブジェクトではありません。ネットワーク接続を確認するか、サーバー管理者に連絡してください。 "

それで、ファイルは存在しませんね?さて、私は自分を次のように変更して作成してみましたCTor()

public OleBase(string connectionString) {
  conStr = connectionString;
  object[] param = new object[] { null, null, null, "TABLE" };
  oleCon = new OleDbConnection(conStr);
  if (-1 < conStr.IndexOf(";IMEX=1;")) {
    string dsString = "Data Source=";
    int dsIndex = conStr.IndexOf(dsString);
    string conSub = conStr.Substring(dsIndex + dsString.Length);
    int firstCol = conSub.IndexOf(';');
    string xlPath = conSub.Substring(0, firstCol);
    if (!File.Exists(xlPath)) {
      File.Create(xlPath);
    }
  }
  oleCon.Open();
  tableNames = oleCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, param);
}

これで、このコードがOleDbConnectionのOpen()メソッドを呼び出そうとすると、次のような異なるOleDbExceptionが発生します。

「MicrosoftAccessデータベースエンジンはファイルを開くことも書き込むこともできません」。すでに別のユーザーによって排他的に開かれているか、データを表示および書き込むためのアクセス許可が必要です。」

StreamWriterを使用してExcelファイルを作成し、基本的なヘッダーを追加してみました。

public OleBase(string connectionString) {
  conStr = connectionString;
  object[] param = new object[] { null, null, null, "TABLE" };
  oleCon = new OleDbConnection(conStr);
  if (-1 < conStr.IndexOf(";IMEX=1;")) {
    string dsString = "Data Source=";
    int dsIndex = conStr.IndexOf(dsString);
    string conSub = conStr.Substring(dsIndex + dsString.Length);
    int firstCol = conSub.IndexOf(';');
    string xlPath = conSub.Substring(0, firstCol);
    using (StreamWriter xls = new StreamWriter(xlPath, false, Encoding.UTF8)) {
      xls.WriteLine("<?xml version=\"1.0\"?><?mso-application progid=\"Excel.Sheet\"?>");
      xls.WriteLine("<ss:Workbook xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" ");
      xls.WriteLine("xmlns:o=\"urn:schemas-microsoft-com:office:office\" ");
      xls.WriteLine("xmlns:x=\"urn:schemas-microsoft-com:office:excel\" ");
      xls.WriteLine("xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">");
      xls.WriteLine("<ss:Styles>");
      xls.WriteLine("<ss:Style ss:ID=\"Default\" ss:Name=\"Normal\"><ss:Alignment ss:Vertical=\"Bottom\"/><ss:Borders/><ss:Font/><ss:Interior/><ss:NumberFormat/><ss:Protection/></ss:Style>");
      xls.WriteLine("<ss:Style ss:ID=\"BoldColumn\"><ss:Font x:Family=\"Swiss\" ss:Bold=\"1\"/></ss:Style>");
      xls.WriteLine("<ss:Style ss:ID=\"StringLiteral\"><ss:NumberFormat ss:Format=\"@\"/></ss:Style>");
      xls.WriteLine("<ss:Style ss:ID=\"Decimal\"><ss:NumberFormat ss:Format=\"0.0000\"/></ss:Style>");
      xls.WriteLine("<ss:Style ss:ID=\"Integer\"><ss:NumberFormat ss:Format=\"0\"/></ss:Style>");
      xls.WriteLine("<ss:Style ss:ID=\"DateLiteral\"><ss:NumberFormat ss:Format=\"mm/dd/yyyy;@\"/></ss:Style>");
      xls.WriteLine("</ss:Styles>");
      xls.WriteLine("</ss:Workbook>");
      xls.Flush();
      xls.Close();
    }
  }
  oleCon.Open();
  tableNames = oleCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, param);
}

このコードは、さらに別のOleDbExceptionメッセージを生成しました。

「外部テーブルが予期された形式ではありません。」

ご覧のとおり、 OleDbConnectionにはファイルを作成するメソッドがないので、このExcelファイルを作成して使用できるようにするにはどうすればよいですか?

4

4 に答える 4

6

私はさまざまなWebサイトに投稿された多くのコードを調べ、最終的には必要なものに非常に適したバージョンを使用しました。

ここに投稿できるようにリンクをブックマークしたかったのですが、何度も失敗した後、追跡を停止したようです。

とにかく、それが他の人を助けるなら、これがExcelWriter私が最終的に作ったクラスです(クラスの使い方はすぐに続きます):

public class ExcelWriter : IDisposable {

  private XmlWriter writer;
  private static readonly DateTime NODATE = new DateTime(1900, 1, 1);

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

  public ExcelWriter(string outputFileName) {
    if (!String.IsNullOrEmpty(outputFileName)) {
      XmlWriterSettings settings = new XmlWriterSettings();
      settings.Indent = true;
      writer = XmlWriter.Create(outputFileName, settings);
    } else {
      throw new Exception("Output path not supplied.");
    }
  }

  public void Close() {
    if (writer != null) {
      writer.Close();
      writer = null;
    } else {
      throw new NotSupportedException("Already closed.");
    }
  }

  public static bool HasValue(object obj) {
    if (obj != null) {
      if (obj != DBNull.Value) {
        string txt = obj.ToString();
        return (0 < txt.Length);
      }
    }
    return false;
  }

  public void WriteStartDocument() {
    if (writer != null) {
      writer.WriteProcessingInstruction("mso-application", "progid=\"Excel.Sheet\"");
      writer.WriteStartElement("ss", "Workbook", "urn:schemas-microsoft-com:office:spreadsheet");
      WriteExcelStyles();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteEndDocument() {
    if (writer != null) {
      writer.WriteEndElement();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  private void WriteExcelStyleElement(CellStyle style) {
    if (writer != null) {
      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) {
    if (writer != null) {
      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() {
    if (writer != null) {
      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) {
      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");
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteEndWorksheet() {
    if (writer != null) {
      writer.WriteEndElement();
      writer.WriteEndElement();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteExcelColumnDefinition(int columnWidth) {
    if (writer != null) {
      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();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteExcelUnstyledCell(string value) {
    if (writer != null) {
      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();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteStartRow() {
    if (writer != null) {
      writer.WriteStartElement("Row", "urn:schemas-microsoft-com:office:spreadsheet");
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteEndRow() {
    if (writer != null) {
      writer.WriteEndElement();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteExcelStyledCell(object value, CellStyle style) {
    if (writer != null) {
      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");
          if (!HasValue(value)) {
            value = String.Empty; // DBNull.Value causes issues in an Excel cell.
          }
          break;
        case CellStyle.Number:
        case CellStyle.Currency:
          writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "Number");
          if (!HasValue(value)) {
            value = 0;
          }
          break;
        case CellStyle.ShortDate:
        case CellStyle.DateTime:
          writer.WriteAttributeString("Type", "urn:schemas-microsoft-com:office:spreadsheet", "DateTime");
          if (!HasValue(value)) {
            value = NODATE;
          }
          break;
      }
      writer.WriteValue(value);
      writer.WriteEndElement();
      writer.WriteEndElement();
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  public void WriteExcelAutoStyledCell(object value) {
    if (writer != null) { //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);
      }
    } else {
      throw new NotSupportedException("Cannot write after closing.");
    }
  }

  #region IDisposable Members

  public void Dispose() {
    if (writer != null) {
      writer.Close();
      writer = null;
    }
  }

  #endregion

}

例:

このクラスを使用して、DataSet全体をExcelブックに書き込む方法は次のとおりです。

  /// <summary>
  /// Saves data to the Access database to the Excel file specified by the filename
  /// </summary>
  public void Save(string excelFile) {
    using (ExcelWriter writer = new ExcelWriter(excelFile)) {
      writer.WriteStartDocument();
      foreach (DataTable table in Dataset.Tables) {
        writer.WriteStartWorksheet(string.Format("{0}", SafeName(table.TableName))); // Write the worksheet contents
        writer.WriteStartRow(); //Write header row
        foreach (DataColumn col in table.Columns) {
          writer.WriteExcelUnstyledCell(col.Caption);
        }
        writer.WriteEndRow();
        foreach (DataRow row in table.Rows) { //write data
          writer.WriteStartRow();
          foreach (object o in row.ItemArray) {
            writer.WriteExcelAutoStyledCell(o);
          }
          writer.WriteEndRow();
        }
        writer.WriteEndWorksheet(); // Close up the document
      }
      writer.WriteEndDocument();
      writer.Close();
    }
  }

他の人がこれから多くの使用法を得ることを願っています!

〜JoeP

于 2012-05-31T13:34:22.520 に答える
3

私は実用的な解決策を見つけました、ちょうどこのようなIMEXパラメータを削除してください:

string connString = String.Format(
    "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};" + 
    "Extended Properties=\"Excel 8.0;HDR={1}\"",
    file,
    (containsHeader ? "Yes" : "No")
);

Excel 12.0を試してみると、ファイルが作成されますが、Excelアプリケーションで開くことができません。

とにかく、これはXLSファイルで機能します。

于 2012-07-11T14:58:06.993 に答える
2

テンプレート(既存の空のExcelファイル)を使用して、そのファイルを必要な名前の新しいExcelファイルにコピーします。それがあなたの創造です!

于 2012-05-31T02:52:29.107 に答える
0

ファイルの読み取り/書き込みを有効にするには、次の属性を使用できます:モード

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=EXCELFILENAME;Mode=ReadWrite;Extended Properties='Excel 12.0 Macro;HDR=YES;'
于 2016-03-03T07:21:52.687 に答える