Excel スプレッドシートのセル値を解析するためのソリューション
は以下のとおりです:
A2 にあるセルを解析します 住所。これは 3 を返します 予想される カテゴリ 1 の代わりの値 .
test.xlsx
using System;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using X = DocumentFormat.OpenXml.Spreadsheet;
namespace DotNetSandbox.SO
{
public class IncorrectCellValue
{
public static void ParseCellValue()
{
using SpreadsheetDocument doc = SpreadsheetDocument.Open(@"c:temptest.xlsx", false);
X.Sheet sheet = doc.WorkbookPart.Workbook.Descendants<X.Sheet>().First();
WorksheetPart wsPart = (WorksheetPart)doc.WorkbookPart.GetPartById(sheet.Id);
X.Cell cell = wsPart.Worksheet.Descendants<X.Cell>().First(c => c.CellReference == "A2");
string cellValue = cell.CellValue.Text;
Console.WriteLine(cellValue);
Console.ReadKey();
}
}
}
出力:
- 対象:.NET 5
- DocumentFormat.OpenXml バージョン:2.13.0
何か間違ったことをしていますか、それともライブラリのバグですか?
この方法を使用してください
public static string GetCellValue(string fileName,
string addressName, string sheetName = "")
{
string value = null;
// Open the spreadsheet document for read-only access.
using (SpreadsheetDocument document =
SpreadsheetDocument.Open(fileName, false))
{
// Retrieve a reference to the workbook part.
WorkbookPart wbPart = document.WorkbookPart;
// Find the sheet with the supplied name, and then use that
// Sheet object to retrieve a reference to the first worksheet.
var theSheets = wbPart.Workbook.Descendants<Sheet>();
Sheet theSheet = string.IsNullOrEmpty(sheetName) ? theSheets.FirstOrDefault() : theSheets.FirstOrDefault(x => x.Name == sheetName);
// Throw an exception if there is no sheet.
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
// Retrieve a reference to the worksheet part.
WorksheetPart wsPart =
(WorksheetPart)(wbPart.GetPartById(theSheet.Id));
// Use its Worksheet property to get a reference to the cell
// whose address matches the address you supplied.
Cell theCell = wsPart.Worksheet.Descendants<Cell>().
Where(c => c.CellReference == addressName).FirstOrDefault();
// If the cell does not exist, return an empty string.
if (theCell.InnerText.Length > 0)
{
value = theCell.InnerText;
// If the cell represents an integer number, you are done.
// For dates, this code returns the serialized value that
// represents the date. The code handles strings and
// Booleans individually. For shared strings, the code
// looks up the corresponding value in the shared string
// table. For Booleans, the code converts the value into
// the words TRUE or FALSE.
if (theCell.DataType != null)
{
switch (theCell.DataType.Value)
{
case CellValues.SharedString:
// For shared strings, look up the value in the
// shared strings table.
var stringTable =
wbPart.GetPartsOfType<SharedStringTablePart>()
.FirstOrDefault();
// If the shared string table is missing, something
// is wrong. Return the index that is in
// the cell. Otherwise, look up the correct text in
// the table.
if (stringTable != null)
{
value =
stringTable.SharedStringTable
.ElementAt(int.Parse(value)).InnerText;
}
break;
case CellValues.Boolean:
switch (value)
{
case "0":
value = "FALSE";
break;
default:
value = "TRUE";
break;
}
break;
}
}
}
}
return value;
}
ここで立ち往生しました:
このコードを実行して、カテゴリ 1 を取得できました:
var cellValue = GetCellValue(@"c:test.xlsx", "A2");
マイクロソフト ドキュメント
メソッドにシート名を渡さない場合、最初のシートを取得するように元のメソッドを変更したことに注意してください。
共有文字列とは:
スプレッドシートでの文字列の使用を最適化するために、SpreadsheetML は文字列の単一インスタンスを共有文字列テーブルと呼ばれるテーブルに保存します。セルは、値をセル値にインラインで格納する代わりに、インデックスによって文字列を参照します。 Excel は、ファイルを保存するときに常に共有文字列テーブルを作成します。