OpenXMLを使用して特定のExcelセルにテキストを書くことに問題がある -- c# フィールド と excel フィールド と openxml フィールド と vba フィールド 関連 問題

Having issue with writing text to specific Excel Cell using OpenXml












2
vote

問題

日本語

私が達成したいのは以下のとおりです。

画像の説明を入力します。ここで

私が後述してきた結果と発行:

これは私のコードが生成され、コンテンツが予想されると思われる結果ファイルです。

画像の説明を入力します。ここで

ウィンドウプロンプト[YES]ボタンをクリックした後。

イメージの説明を入力します。ここで

私の実行コードは以下のとおりです。

主な方法:

<事前> <コード> public static void Main(string[] args) { WriteExcelService writeExcelService = new WriteExcelService(); Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>> { { "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) }, { "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) } }; string inputFile = @"C:{username}DesktopValentines_Day.xlsx"; string sheetName = "Copy"; writeExcelService.WriteValueToCell(inputFile, sheetName, contentList); }

writevaleetocell法:

<事前> <コード> char columnName = 'I'; uint rowNumber = 1; foreach (var keys in contentList.Keys) { foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value)) { string cellAddress = String.Concat(columnName, rowNumber); this.Write(filepath, sheetName, value, cellAddress, rowNumber); int tempColumn = (int)columnName; columnName = (char)++tempColumn; } columnName = 'I'; ++rowNumber; }

書き込み方法:

<事前> <コード> private void Write(string filepath, string sheetName, string value, string cellAddress,uint rowNumber) { // Create a spreadsheet document by supplying the filepath. // By default, AutoSave = true, Editable = true, and Type = xlsx. using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)) { //writeExcelService.WriteValueToCell(outputFilePath, sheetName, cellAddress, value.Value); // Add a WorkbookPart to the document. WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); // Add a WorksheetPart to the WorkbookPart. WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); worksheetPart.Worksheet = new Worksheet(new SheetData()); // Add Sheets to the Workbook. Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets()); // Append a new worksheet and associate it with the workbook. Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = sheetName }; sheets.Append(sheet); // Get the sheetData cell table. SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); // Add a row to the cell table. Row row; row = new Row() { RowIndex = rowNumber }; sheetData.Append(row); // In the new row, find the column location to insert a cell. Cell refCell = null; foreach (Cell cell in row.Elements<Cell>()) { if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0) { refCell = cell; break; } } // Add the cell to the cell table. Cell newCell = new Cell() { CellReference = cellAddress }; row.InsertBefore(newCell, refCell); // Set the cell value to be a numeric value. newCell.CellValue = new CellValue(value); newCell.DataType = new EnumValue<CellValues>(CellValues.Number); } }

私の問題は次のとおりです。

私のコードが実行されますが、結果ファイルが開いていると、上記の通知としてウィンドウが表示され、ファイルは空です。コンテンツのリストを1つずつ挿入するためにコードをデバッグするには、セルに正しく書き込める<コード> I2 または<コード> J2 。コードコンテンツごとに SpreadsheetDocument が作成されているため、以下のコードで<コード> SpreadsheetDocument 作成方法を変更しました。

<事前> <コード> using (SpreadsheetDocument spreadsheetDocument = File.Exists(filePath) ? SpreadsheetDocument.Open(filepath, true) : SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)) { }

しかし、私は例外を取得しています

この親に使用できるタイプのインスタンスは1つだけです。

誰もが私を助けることができますか?

事前にそれを感謝しています。

英語

What I want to achieve is illustrated below:

enter image description here

The result and issue I've been having are illustrated below:

This is the result file my code has generated and there supposed to have expected content.

enter image description here

Window prompt after the 'Yes' button has clicked.

enter image description here

My running code is given below:

Main method:

public static void Main(string[] args) {     WriteExcelService writeExcelService = new WriteExcelService();     Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>>     {         { "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) },         { "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) }     };     string inputFile = @"C:{username}DesktopValentines_Day.xlsx";     string sheetName = "Copy";      writeExcelService.WriteValueToCell(inputFile, sheetName, contentList); } 

WriteValueToCell method:

char columnName = 'I';         uint rowNumber = 1;         foreach (var keys in contentList.Keys)         {             foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value))             {                 string cellAddress = String.Concat(columnName, rowNumber);                 this.Write(filepath, sheetName, value, cellAddress, rowNumber);                 int tempColumn = (int)columnName;                 columnName = (char)++tempColumn;             }             columnName = 'I';             ++rowNumber;         } 

Write method:

private void Write(string filepath, string sheetName, string value, string cellAddress,uint rowNumber) {     // Create a spreadsheet document by supplying the filepath.     // By default, AutoSave = true, Editable = true, and Type = xlsx.     using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook))     {         //writeExcelService.WriteValueToCell(outputFilePath, sheetName, cellAddress, value.Value);         // Add a WorkbookPart to the document.         WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();         workbookpart.Workbook = new Workbook();          // Add a WorksheetPart to the WorkbookPart.         WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();         worksheetPart.Worksheet = new Worksheet(new SheetData());          // Add Sheets to the Workbook.         Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());          // Append a new worksheet and associate it with the workbook.         Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = sheetName };         sheets.Append(sheet);          // Get the sheetData cell table.         SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();          // Add a row to the cell table.         Row row;         row = new Row() { RowIndex = rowNumber };         sheetData.Append(row);          // In the new row, find the column location to insert a cell.         Cell refCell = null;         foreach (Cell cell in row.Elements<Cell>())         {             if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0)             {                 refCell = cell;                 break;             }         }          // Add the cell to the cell table.         Cell newCell = new Cell() { CellReference = cellAddress };         row.InsertBefore(newCell, refCell);          // Set the cell value to be a numeric value.         newCell.CellValue = new CellValue(value);         newCell.DataType = new EnumValue<CellValues>(CellValues.Number);     } } 

My problem is:

My code executes but once the result file is opened, It prompts window as I posted above, and the file is empty.If I debug the code to insert list of contents one by one, it can be written correctly to Cells I2 or J2. Since my code creates SpreadsheetDocument for each list content, therefore I have changed the SpreadsheetDocument creation approach in the code below:

using (SpreadsheetDocument spreadsheetDocument = File.Exists(filePath) ? SpreadsheetDocument.Open(filepath, true) :  SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook))    {     } 

But I am getting exception

Only one instance of the type is allowed for this parent.

Anyone can help me on this?

Appreciate it in advance.

</div
           
   
   

回答リスト

3
 
vote

Excelの文字列は sharedStringTable の下に保存されます。文字列を挿入するときは、文字列を追加するか、 sharedstringtable から文字列を参照することが重要です。また、セルに正しい private static void printReport(String filename, String str) throws Exception /* No, it doesn't. The only calls you had outside your catch-all `try` don't throw exceptions. */ { ErrorCheck ec = new ErrorCheck(); // Recommend not creating this until/unless you need it String fileName = "/var/Emails_log/"+filename; // VERY poor practice having two locals that only differ by the capitalization of one character in the middle (`filename` and `fileName`) Path filePath = Paths.get(fileName); // File file = new File(fileName); <== Removed, since you never use it for anything try { // Make sure the directories exist Files.createDirectories(filePath.getParent()); // No need for your null check, so I removed it; based on `fileName`, it will always have a parent // Open the file, creating it if it doesn't exist try ( final BufferedWriter out = Files.newBufferedWriter( filePath, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND) ) { // Write to out here } } catch (Exception e) { // Log-and-continue isn't generally best practice; and if you're going to do it ec.errorMsg("ERROR: GSW.SendEmail.Exception =>",e); // <== Um...send mail failed? This isn't sending mail, it's putting something in a file. } // Using the try-with-resources, we don't have to worry about the flush and close calls } 5 を指定する必要があります。コードでは、すべての値を数値として挿入しています。

<事前> <コード> newBufferedWriter16

文字列を挿入するには、新しいセルを作成した後に次の方法を使用することをお勧めします。

<事前> <コード> private static void printReport(String filename, String str) throws Exception /* No, it doesn't. The only calls you had outside your catch-all `try` don't throw exceptions. */ { ErrorCheck ec = new ErrorCheck(); // Recommend not creating this until/unless you need it String fileName = "/var/Emails_log/"+filename; // VERY poor practice having two locals that only differ by the capitalization of one character in the middle (`filename` and `fileName`) Path filePath = Paths.get(fileName); // File file = new File(fileName); <== Removed, since you never use it for anything try { // Make sure the directories exist Files.createDirectories(filePath.getParent()); // No need for your null check, so I removed it; based on `fileName`, it will always have a parent // Open the file, creating it if it doesn't exist try ( final BufferedWriter out = Files.newBufferedWriter( filePath, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND) ) { // Write to out here } } catch (Exception e) { // Log-and-continue isn't generally best practice; and if you're going to do it ec.errorMsg("ERROR: GSW.SendEmail.Exception =>",e); // <== Um...send mail failed? This isn't sending mail, it's putting something in a file. } // Using the try-with-resources, we don't have to worry about the flush and close calls } 7
 

Strings in excel are saved under a sharedStringTable. When inserting a string it is important to add the string or reference the string from the sharedStringTable. Also, you need to provide the correct DataType for a cell. In your code, you are inserting all values as a number:

// Set the cell value to be a numeric value. newCell.CellValue = new CellValue(value); newCell.DataType = new EnumValue<CellValues>(CellValues.Number); 

To insert a string I would recommend using the following method after you have created a new cell:

private SpreadsheetDocument _spreadSheet; private WorksheetPart _worksheetPart; .. .. private void UpdateCell(Cell cell, DataTypes type, string text) {     if (type == DataTypes.String)     {         cell.DataType = CellValues.SharedString;          if (!_spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Any())         {             _spreadSheet.WorkbookPart.AddNewPart<SharedStringTablePart>();         }          var sharedStringTablePart = _spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();         if (sharedStringTablePart.SharedStringTable == null)         {             sharedStringTablePart.SharedStringTable = new SharedStringTable();         }         //Iterate through shared string table to check if the value is already present.         foreach (SharedStringItem ssItem in sharedStringTablePart.SharedStringTable.Elements<SharedStringItem>())         {             if (ssItem.InnerText == text)             {                 cell.CellValue = new CellValue(ssItem.ElementsBefore().Count().ToString());                 return;             }         }         // The text does not exist in the part. Create the SharedStringItem.         var item = sharedStringTablePart.SharedStringTable.AppendChild(new SharedStringItem(new Text(text)));         cell.CellValue = new CellValue(item.ElementsBefore().Count().ToString());     }     else if (type == DataTypes.Number)     {         cell.CellValue = new CellValue(text);         cell.DataType = CellValues.Number;     }     else if (type == DataTypes.DateTime)     {          cell.DataType = CellValues.Number;         cell.StyleIndex = Convert.ToUInt32(_dateStyleIndex);          DateTime dateTime = DateTime.Parse(text);         double oaValue = dateTime.ToOADate();         cell.CellValue = new CellValue(oaValue.ToString(CultureInfo.InvariantCulture));     }     _worksheetPart.Worksheet.Save(); } 
</div
 
 
         
         
2
 
vote
vote
ベストアンサー
 

私は解決策を自分で考え出しました。私は文字列の内容のリストを渡し、それらを対応するセルにすべてを書き込み、 SpreadSheetDocument を閉じます。このようにして<コード> SpreadSheetDocument を1回作成できます。ワーキングコードは以下のとおりです。

<事前> <コード> public void WriteValueToCell(string filepath, string sheetName, Dictionary<string, List<string>> contentList) { // Create a spreadsheet document by supplying the filepath. // By default, AutoSave = true, Editable = true, and Type = xlsx. using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook, true)) { // Add a WorkbookPart to the document. WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); //Add a WorkbookStylesPart to the workbookpart WorkbookStylesPart stylesPart = workbookpart.AddNewPart<WorkbookStylesPart>(); stylesPart.Stylesheet = new Stylesheet(); // Add a WorksheetPart to the WorkbookPart. WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); worksheetPart.Worksheet = new Worksheet(new SheetData()); // Add Sheets to the Workbook. Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets()); // Append a new worksheet and associate it with the workbook. Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = sheetName }; sheets.Append(sheet); // Get the sheetData cell table. SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); char columnName = 'I'; uint rowNumber = 1; foreach (var keys in contentList.Keys) { foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value)) { string cellAddress = String.Concat(columnName, rowNumber); // Add a row to the cell table. Row row; row = new Row() { RowIndex = rowNumber }; sheetData.Append(row); // In the new row, find the column location to insert a cell. Cell refCell = null; foreach (Cell cell in row.Elements<Cell>()) { if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0) { refCell = cell; break; } } // Add the cell to the cell table. Cell newCell = new Cell() { CellReference = cellAddress }; row.InsertBefore(newCell, refCell); // Set the cell value to be a numeric value. newCell.CellValue = new CellValue(value); newCell.DataType = new EnumValue<CellValues>(CellValues.String); int tempColumn = (int)columnName; columnName = (char)++tempColumn; } columnName = 'I'; ++rowNumber; } } }

主な方法:

<事前> <コード> public static void Main(string[] args) { WriteExcelService writeExcelService = new WriteExcelService(); Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>> { { "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) }, { "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) } }; string inputFile = @"C:{username}DesktopValentines_Day.xlsx"; string sheetName = "Copy"; writeExcelService.WriteValueToCell(inputFile, sheetName, contentList); }
 

I have figured out the solution myself. I have passed the list of string contents and write them all to corresponding Cells then closed the SpreadSheetDocument. In this way SpreadSheetDocument can be created once. Working code is below:

public void WriteValueToCell(string filepath, string sheetName, Dictionary<string, List<string>> contentList) {     // Create a spreadsheet document by supplying the filepath.     // By default, AutoSave = true, Editable = true, and Type = xlsx.     using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook, true))     {         // Add a WorkbookPart to the document.         WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();         workbookpart.Workbook = new Workbook();          //Add a WorkbookStylesPart to the workbookpart         WorkbookStylesPart stylesPart = workbookpart.AddNewPart<WorkbookStylesPart>();         stylesPart.Stylesheet = new Stylesheet();          // Add a WorksheetPart to the WorkbookPart.         WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();         worksheetPart.Worksheet = new Worksheet(new SheetData());          // Add Sheets to the Workbook.         Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());          // Append a new worksheet and associate it with the workbook.         Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = sheetName };         sheets.Append(sheet);          // Get the sheetData cell table.         SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();          char columnName = 'I';         uint rowNumber = 1;         foreach (var keys in contentList.Keys)         {             foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value))             {                 string cellAddress = String.Concat(columnName, rowNumber);                 // Add a row to the cell table.                 Row row;                 row = new Row() { RowIndex = rowNumber };                 sheetData.Append(row);                  // In the new row, find the column location to insert a cell.                 Cell refCell = null;                 foreach (Cell cell in row.Elements<Cell>())                 {                     if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0)                     {                         refCell = cell;                         break;                     }                 }                  // Add the cell to the cell table.                 Cell newCell = new Cell() { CellReference = cellAddress };                 row.InsertBefore(newCell, refCell);                 // Set the cell value to be a numeric value.                 newCell.CellValue = new CellValue(value);                 newCell.DataType = new EnumValue<CellValues>(CellValues.String);                  int tempColumn = (int)columnName;                 columnName = (char)++tempColumn;             }             columnName = 'I';             ++rowNumber;         }     } } 

Main method:

public static void Main(string[] args) {     WriteExcelService writeExcelService = new WriteExcelService();     Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>>     {         { "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) },         { "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) }     };     string inputFile = @"C:{username}DesktopValentines_Day.xlsx";     string sheetName = "Copy";      writeExcelService.WriteValueToCell(inputFile, sheetName, contentList); } 
</div
 
 
         
         

関連する質問

0  Excel 2003でExcelマクロランタイムエラー428  ( Excel macro runtime error 428 in excel 2003 ) 
互換モードでExcel 2007でうまく機能するXLT Excelテンプレートを作成し、互換性チェックにエラーがないことを示しています。テンプレートは、ピボットテーブルとチャートを作成する多数のマクロを実行します。 同僚がExcel 2003で同じXLTを実行...

3  Excelマクロをスピードアップしますか?  ( Speed up an excel macro ) 
今私はマクロ<コード> PopulateYearlyValues を持っていますが、それは私には長すぎるようです <事前> <コード> Sub PopulateYearlyValues(ByVal Month As Range) Dim c As Do...

0  WebサービスからExcel VBAへのC#リストを返す  ( Returning c sharp lists from a web service to excel vba ) 
これは長い1つの謝罪です.... Webサービスを介してC#からVBAまでのC#からVBAへの復帰リストの信頼性はありますか? いくつかのダブル、文字列などで構成される 'result'を返すWebサービスを持っています(それはエンジニアリング計算です)。...

3  VBAでExcelチャートにDataPointを追加する  ( Adding datapoint to excel chart with vba ) 
チャートオブジェクトを持っている3シリーズ。シリーズは範囲C1:C10、D1:D10、E1:E10の範囲からY値を取得しています。値は、A1:A10の値に依存します(例:C1 = A1 + 6)。ただし、B1:10(その対数通常グラフ)の値に対する値をチャート...

1  MSEXCELからのSSL対応サービスを呼び出す?  ( Calling ssl enabled services from msexcel ) 
私はWeb Sphereに展開されていて、このサービスはSSLが有効になっています。私はMS Excelからこのサービスを呼ばなければなりません。私はMySoaplib.SoapClientを使って私のWebサービスを呼び出しています。このマクロを実行すると、...

1  ExcelのVBAからアドイン機能を呼び出す  ( Calling a add in function from excels vba ) 
ErlangのExcelアドインを使用しています: http://abstractmicro.com/erlang/helppages/ref-erlbblockage.htmud/a. > VBA内のアドイン内のERLANG-B関数を呼び出してみまし...

2  マクロを介して内容表(TOC)を作成する方法  ( How to create table of contents toc via macro ) 
TCフィールドからのTOCフィールドの更新をサポートしていない場合は、マクロによるMailMergeの後に内容を作成する必要があります。 TOCの作成を自動化することは可能ですか? ...

0  選択方法でExcel VBAを使用してテーブルのサブセットを選択する方法 - >から>>  ( How to select a subset of a table with excel vba in the manner of select from ) 
謝罪は古典的なニュービーの質問ですが、私は具体的な答えを見つけることができなかった。 私は完全にExcel VBAと一般的にプログラミングすることができました。私がしようとしていることは、大きなExcelシートからのデータのサブセットを選択することです。 <前...

3  Excelマクロプロシージャの実行可能アプリケーションを作成する方法  ( How do i create an executable application for a excel macro procedure ) 
2つのスプレッドシート(​​ "古い"と "new")とVBスクリプトマクロを持っています。マクロは1つ( "New")で実行され、もう一方の内容( "old")の比較を行い、結果を "New"スプレッドシートに戻す。 私が2つのファイル名を入力して実行ボタ...

3  Excel VBAのグローバルアレイ対グローバルアレイの長所と短所とは何ですか  ( What are pros cons of passed arrays vs global arrays in excel vba ) 
OK、スタックオーバーフロー質問を書くことに2回目の試み、これがおなじみのように思えるのであれば私を許してください。 私は、2年間の1年間で建設されたExcelマクロを書き換えています.Frankenstein Style(断片的に追加されました)。私がす...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有