【问题标题】:Problem reading numbers from excel with PHPExcel使用 PHPExcel 从 excel 中读取数字时出现问题
【发布时间】:2011-04-22 08:02:59
【问题描述】:

我正在尝试使用 PHPExcel 从 excelsheet 中读取一个数字。

读取数据的代码:

$objReader = PHPExcel_IOFactory::createReaderForFile($upload_file);
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($upload_file);
$objWorksheet = $objPHPExcel->getActiveSheet();
$data = array();

$i = 0;

foreach ($objWorksheet->getRowIterator() as $row) {
    if ($i < 1) {
    $i++; 
    continue; //Skip heading titles
}
$cellIterator = $row->getCellIterator();        
$cellIterator->setIterateOnlyExistingCells(false);      
foreach ($cellIterator as $cell) {          
    $data [$i] [] = $cell->getValue();          
}       
$i ++;

代码有效。我阅读了 Excel,所有数据都很好地保存在 $data 数组中。 问题出在 A 列中,我得到了一个数字( 4078500264822 )。它返回为“4078500264820”(见最后一个 0)。不管我怎么读。如果我打印整行,我发现值是错误的。当我使用诸如“getCalculatedValue”之类的函数时,结果是一样的。

我认为这与字段在 excel 中的保存方式有关。我将其保存为“数字”类型。 在另一排。我保存了相同的号码。这次是“文本”(excel 会对此发出通知)。 PHPExcel 可以读取该数字。我有一个 40 记录表。其中 26 个单元格的最后一个数字被 0 替换。您可以在此处找到一个截断的文件(仅 2 行) --> http://dl.dropbox.com/u/1458083/excel.xlsx

【问题讨论】:

    标签: php phpexcel


    【解决方案1】:

    或者也许只是尝试 ini_set("precision", "15");默认值为 12。为我工作。

    【讨论】:

    • 感谢您的帮助
    【解决方案2】:

    你在哪个平台上?

    在我的 Mac 上,使用 MacPorts 的(64 位)PHP 解释器和 PHPExcel 1.7.6,我似乎得到了正确的值:

    array (
      1 => 
      array (
        0 => 4078500264822,
        1 => '02648-32.000.00',
        2 => 'Wand-slangenbox automatic',
        3 => '20m slang, rolt zichzelf gelijkmatig op na gebruik. Geïntegreerde draaggreep voor 
    comfortabel transport, inclusief montagemateriaal en wand-/vloerhouder.',
        4 => 17400,
        5 => 119.95,
        6 => '',
        7 => 12,
      ),
      2 => 
      array (
        0 => '4078500888707',
        1 => '08887-20.000.00',
        2 => 'Accu gras-buxusschaar set',
        3 => 'Eenvoudig gras en buxus in vorm knippen zonder storende kabels. De messen kunnen worden verwisseld zonder gereedschap, het is bijzonder gemakkelijk, snel en veilig. Laat tevens op tijd zien wanneer de accu weer moet worden opgeladen. ',
        4 => 16340,
        5 => 69.95,
        6 => 79.95,
        7 => 12,
      ),
    )
    

    运行时的输出是什么:

    $ php -r 'echo PHP_INT_MAX;'
    

    如果是 2147483647,请尝试 64 位解释器。或者向 PHPExcel 提交请求以修复强制转换。

    【讨论】:

    • 这是最奇怪的事情。 PHP_INT_MAX 返回 2147483647 没有我的生活(linux)和测试环境(测试本地主机,windows)。尝试完全相同的导入确实可以在本地主机上工作。将号码保存为“文本”并不能解决问题。不幸的是,仅仅更改为 64 位环境是不可能的 :(
    【解决方案3】:

    如果值在 Excel 中存储为字符串,则在将其加载到 PHPExcel 中时它将存储为字符串(假设您使用的是默认值绑定器...高级值绑定器肯定会导致您问题,因为它的目的是处理转换为更合适的数据类型)。如果它在 Excel 中存储为数字,那么精度在加载到 PHPExcel 之前就会丢失。

    你可以做的是设置你自己的值绑定器(扩展默认值绑定器),使用 bindValue() 方法测试正在读取的单元格的列引用(查看它是否是列 A),并强制PHPExcel 将该值存储为字符串(即使已从 Excel 文件中读取数字)。

    编辑

    这个活页夹应该按照我的建议做,强制 PHPExcel 将 A 列中的所有值作为字符串加载。

    class SpecialValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder
    {
        public function bindValue(PHPExcel_Cell $cell, $value = null)
        {
            if ($cell->getColumn() == 'A') {
                $value = PHPExcel_Shared_String::SanitizeUTF8($value);
                $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING);
                return true;
            }
    
            // Not bound yet? Use parent...
            return parent::bindValue($cell, $value);
        }
    }
    
    
    /**  Tell PHPExcel that we want to use our Special Value Binder  **/
    PHPExcel_Cell::setValueBinder( new SpecialValueBinder() );
    

    确保您定义了活页夹,并告诉 PHPExcel 在执行 load() 之前 使用它

    编辑 2

    正如 crishoj 所做的那样,我已经运行了您的代码(在 Windows 上使用 32 位 PHP)。 var_dump() 将值 4078500264822 作为浮点数返回,这是我所期望的(该值太大而无法存储为 32 位整数),并且回显它会显示相同的正确值,而不会损失准确性.

    【讨论】:

    • 您说“精度在加载到 PHPExcel 之前就丢失了”。这是否意味着我只需将 A 列强制为文本类型?我现在已经测试了更多,似乎确实当我上传时我得到了一个浮点数:float(4078500264820)。如果我强制该列是文本,它可以工作。 (您的代码也将其转换为字符串。但就像您说的那样。精度已经丢失)。
    • 我不好。我一直在检查 excel.xlsx 文件的来源,并且 Excel 正在存储完整值,因为它实际上作为纯文本值完整存储在工作表 XML 文件中。如果您使用的是 xls 文件,那么它将存储为 64 位浮点数,这会导致 Excel 本身不精确。因为单元格类型是数字,PHPExcel 默认行为是在加载文件时将其转换为浮点数(因为 32 位整数不能保存该大小的值),这种转换可能会导致精度损失.
    • 特殊绑定器强制将值视为文本(与从 xlsx 文件中读取的一样),而不是按照类型指示将其强制转换为浮点数。因为这里没有强制浮动,所以保存在 xlsx 文件的 xml 中的字符串值保持“原样”,因此不会丢失精度。
    • 进行了更多测试。似乎A列的数据在进入bindValue之前已经是一个浮点数。如果我在转换它之前 var_dump $value 它已经是一个带有错误数字的浮点数。我假设它是在 $objReader->load() 函数中转换的。我可以在那里覆盖它以将所有内容都视为字符串吗?
    【解决方案4】:

    感谢 Mark 和 crishoj 的支持。不幸的是它没有解决问题;( 我不能在这里给任何人正确的解决方案,因为我的数据显然在调用 Excel 加载函数之前就已损坏。

    我通过强制我的客户使用 CSV 解决了这个问题。这是代码中的一个非常小的变化(又名。1 行,PHPExcel == 真棒!)现在我将所有内容都作为字符串接收(因此,它可以工作!)

    再次感谢大家的帮助。

    【讨论】:

    • 这里我们解决方案是为了帮助别人,因为库不属于任何人,实际上库是开源的救世主
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多