4

現在、OpenXML SDK を使用していますが、OpenXML の値と比べて Excel に表示される値に問題があります。

基本的に、B4の値が「202」のExcelスプレッドシートがあります。しかし、OpenXml を使用してスプレッドシートから値を読み取ると、受け取る値は「201.99999999999997」です。

値を確認するテスト アプリを作成しました。OpenXml を使用して Excel ファイルを読み取るために使用しているコードは次のとおりです。

using (SpreadsheetDocument document = SpreadsheetDocument.Open(_excelFile1, false))
{
    WorkbookPart wbPart = document.WorkbookPart;

    var sheet = wbPart.Workbook.Descendants<Sheet>().First();

    var wsPart = (WorksheetPart)(wbPart.GetPartById(sheet.Id));

    Cell cell1 = wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference == "B4").FirstOrDefault();
    Cell cell2 = wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference == "C4").FirstOrDefault();
    Cell cell3 = wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference == "D4").FirstOrDefault();

    Console.WriteLine(String.Format("Cell B4: {0}", GetCellValue(cell1)));
    Console.WriteLine(String.Format("Cell C4: {0}", GetCellValue(cell2)));
    Console.WriteLine(String.Format("Cell D4: {0}", GetCellValue(cell3)));
}

private static string GetCellValue(Cell cell)
{
    if (cell != null) return cell.CellValue.InnerText;
    else return string.Empty;
}

次に、取得する値は次のとおりです。

Cell B4: 201.99999999999997

[更新 - XLSX ファイルからの生の XML]

<row r="4" spans="1:4" x14ac:dyDescent="0.2">
    <c r="A4" s="2">
        <v>39797</v>
    </c>
  <c r="B4" s="3">
    <v>201.99999999999997</v>
  </c>
  <c r="C4" s="3">
    <v>373</v>
  </c>
  <c r="D4" s="3">
    <v>398</v>
  </c>
</row>

XLSX ファイルの XML からわかるように、OpenXML は正しい値を読み取っています。ただし、Excel は、値 "201.99999999999997" を "202" として表示するために、何らかの書式設定を適用している必要があります。これはユーザーに表示される値であるため、OpenXML を使用して XLSX ファイルから読み取るときに期待する値です。

だから今、スプレッドシートでユーザーが見るのと同じように値を取得するためにExcelによって適用されるフォーマットを誰かが知っているかどうか疑問に思っていますが、OpenXMLを使用しています。

テストとしてスプレッドシートを再作成してみましたが、スプレッドシートに整数を入力すると、値が 10 進数と同じように表示されることがあります。それは非常に断続的であり、問​​題を説明したり修正したりすることはできません。

4

1 に答える 1

3

201.99999999999997 は、浮動小数点数の実数表現です。常に正確であるとは限りません。詳細については、こちらの例を参照してください。そうです、ある種のフォーマット (有効数字) を適用することをお勧めします。.NET でも同じことができます。これを見てください。

    static void Main(string[] args)
    {
        string s = "201.99999999999997";
        // print s as string
        Console.WriteLine(s);
        // print s as double
        Console.WriteLine(double.Parse(s, System.Globalization.CultureInfo.InvariantCulture));
        // print s as double, converted back to string
        Console.WriteLine(double.Parse(s, System.Globalization.CultureInfo.InvariantCulture).ToString());
        Console.ReadKey();

        // output is:
        // 201.99999999999997
        // 202
        // 202
    }

したがって、数値が必要な場合は、「201.99999999999997」を数値に変換してください。数値の文字列表現が必要な場合は、それを数値に変換してから文字列に戻します。

于 2013-04-19T08:11:29.880 に答える