21

I have an array that can store numbers in such as 01, 01A, 01B, 02, 2, and When I get this value using PHPExcel, it's being removed the '0's in case of 01, 02, for example. To solve this problem, I tried to format the row where these values will be stored in excel and set it as text type, just like in the following code:

    $objPHPExcel->setActiveSheetIndexByName('BlocksList');
    $objPHPExcel->getActiveSheet()->fromArray($blockNames, null, 'A2');
    $latestBLColumn = $objPHPExcel->getActiveSheet()->getHighestDataColumn();
    $column = 'A';
    $row = 1;
    for ($column = 'A'; $column != $latestBLColumn; $column++) {
        $objPHPExcel->getActiveSheet()->getStyle($column.$row)->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_TEXT );
    }
    $objPHPExcel->getActiveSheet()->fromArray($blockNames, null, 'A1');

So, by doing this, I get the array with numbers like 01, 01A, 02, 02B... and I store it in the Row A2. I get the highest Column to use this value in the condition For. In this condition, I set for the Row 1 in the range A until the highest column, to be formated as text.

My template is generated, and all the numbers are in text format, but the problem is that I think when I use the "fromArray()" method, it transforms the numbers of the array before I can get it right in excel. Do you have any idea of how can I solve this problem??

sergioviniciuss
  • 4,596
  • 3
  • 36
  • 50

6 Answers6

34

Formatting using a number format affects the way a number is displayed, not the way it is stored.

You'll have to store the numbers explicitly as strings, so you can't use fromArray(). Use setCellValueExplicit() or setCellValueExplicitByColumnAndRow() instead, passing a $pDataType argument of PHPExcel_Cell_DataType::TYPE_STRING.

EDIT

Note that you can also set styles for a range of cells, so there's no need to add the overhead of the for loop:

$range = 'A'.$row.':'.$latestBLColumn.$row;
$objPHPExcel->getActiveSheet()
    ->getStyle($range)
    ->getNumberFormat()
    ->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_TEXT );

EDIT #2 Using a cell binder

Create a customised cell value binder:

class PHPExcel_Cell_MyValueBinder extends PHPExcel_Cell_DefaultValueBinder
    implements PHPExcel_Cell_IValueBinder 
{ 
    public function bindValue(PHPExcel_Cell $cell, $value = null) 
    { 
        // sanitize UTF-8 strings 
        if (is_string($value)) { 
            $value = PHPExcel_Shared_String::SanitizeUTF8($value); 
        } 

        // Implement your own override logic 
        if (is_string($value) && $value[0] == '0') { 
            $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); 
            return true; 
        } 

        // Not bound yet? Use default value parent... 
        return parent::bindValue($cell, $value); 
    } 
} 

To avoid any problems with the autoloader, create this in the /Classes/PHPExcel/Cell directory. Otherwise, give the class your own non-PHPExcel name, and ensure that it's loaded independently.

Then, before using your fromArray() call, tell PHPExcel to use your value binder instead of the default binder:

PHPExcel_Cell::setValueBinder( new PHPExcel_Cell_MyValueBinder() );
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • so if I have an array with 1000 values, I'll have to set each of its elements as string? – sergioviniciuss Sep 17 '12 at 10:52
  • 2
    Sorry, but yes - fromArray() is a shortcut, but limited in its flexibility so it "guesses" datatypes (the cell default value binder handles this)... the alternative is to set a custom value binder that would always treat a string as a string, even if that string value is number; then you could use fromArray(). – Mark Baker Sep 17 '12 at 10:56
  • Do you know how could I set this custom value binder? This idea sounds good to me – sergioviniciuss Sep 17 '12 at 11:08
  • /Tests/29advancedvaluebinder.php shows how to set a value binder. You'd need to write your own value binder, but could use either the existing default or advanced value binders as the basis for this – Mark Baker Sep 17 '12 at 11:20
  • It's probably easiest to use the default value binder as the basis, and modify the preg_match test that tests for numeric to exclude values with a leading zero followed by a digit, or add an additional if test just before that which identifies the strings with a leading zero and returns PHPExcel_Cell_DataType::TYPE_STRING – Mark Baker Sep 17 '12 at 11:25
  • Do you mean in this function dataTypeForValue($pValue)? – sergioviniciuss Sep 17 '12 at 12:19
  • 1
    That's the one - that's the code that looks at the value you're setting for the cell, and that determines whether it's a number, string, rich text (inline), boolean, etc. The bindValue() function is the one that actually sets the cell value: the equivalent function in the advanced value binder sets (for example) a boolean type if the value being set for the cells is a string containing 'TRUE'; and also sets styles for certain cells automatically – Mark Baker Sep 17 '12 at 12:23
  • thanks so much for this! it is kinda inperformant, though. is there anything you can to about that? – Alex Feb 20 '14 at 11:35
  • I can add it to the very long list of tasks awaiting my attention, but that's the best I can do at this point in time; but if you create a custom binder it's going to be as performant as you make it. You have the option of manually setting datatypes explicitly anyway, bypassing any binders – Mark Baker Feb 20 '14 at 12:46
  • @user2508485 - If you want to ask a question, then ask question - DO NOT EDIT AN EXISTING ANSWER TO ANOTHER QUESTION – Mark Baker May 23 '16 at 09:30
  • it not working, Cell value =7 , format display is 7.0. After setFormatCode, result =7 – D T Dec 28 '17 at 04:26
9

In case you need to convert the whole sheet numbers to text, you can use calculateWorksheetDimension() to get the sheet's dimensions (example: 'A1:B200' or 'A1:C150') and then use it in getStyle(), like so:

// Get sheet dimension
$sheet_dimension = $spreadsheet->getActiveSheet()->calculateWorksheetDimension();

// Apply text format to numbers
$spreadsheet->getActiveSheet()->getStyle($sheet_dimension)->getNumberFormat()->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_TEXT);

Note: This example uses PhpSpreadsheet since it is the next version of PHPExcel.

Jimmy Adaro
  • 1,325
  • 15
  • 26
7

I know this was all posted a while ago, but wanted to share something that worked for me, so you can still use ->fromArray and not have to iterate over the whole spreadsheet.

If you wrap your values in ="VALUE" it will come through as text, and not convert it, and it will not have quotes around it in your spreadsheet

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
Arkitecht
  • 71
  • 1
  • 3
5
$objPHPExcel
   ->getActiveSheet()
   ->getCellByColumnAndRow($col, $row)
   ->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING);
Unamata Sanatarai
  • 6,475
  • 3
  • 29
  • 51
Hưng
  • 51
  • 1
  • 1
2

Try this :

$objPHPExcel->getActiveSheet()->setCellValueExplicit("A1","yourvalue",PHPExcel_Cell_DataType::TYPE_STRING);

please see here setCellValueExplicit function : https://github.com/PHPOffice/PHPExcel/blob/1.8/Classes/PHPExcel/Worksheet.php

Pakerou
  • 21
  • 2
  • 2
    Hi please explain the reasoning that led you to this code, code only answer will be flagged as low effort. – Paulo Sep 13 '21 at 08:20
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 13 '21 at 09:56
1

You can format value to text with add charater before or after value. Example add after value charater ";"

$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(1, $row,$user->msisdn.';' );
Saagar Elias Jacky
  • 2,684
  • 2
  • 14
  • 28
user3313585
  • 189
  • 1
  • 3
  • 1
    This is a terrible solution. Very unprofessional towards your clients in case they need Excel exports. It works but it's very dirty. Better option is converting your integers to strings with either strval($var) or (string) $var. –  Feb 21 '18 at 09:43