Exportação para XLS

Pessoal, bom dia!

Estou fazendo a exportação de uma consulta para XLS. Essa não é uma exportação nativa do scriptcase devido a algumas necessidades que tive.

O meu problema está sendo que ao exportar para o XLS, tenho um campo valor que está importando de forma incorreta. Pelo que percebi, valores maiores de 1000 ou que contenham os centavos (por ex: 855,14) Estão exportando corretos. Porém numeros cheios (por ex: 800) vai no fim como 800 mesmo.

Abaixo, o código de como estou fazendo:

HTML montado:

$html = '';
$html .= '<table '.$style_table.'>';
$html .= '   <tr>';
$html .= '       <td><b><center>Admissão</center></b></td>';
$html .= '       <td><b><center>Nome</center></b></td>';
$html .= '       <td><b><center>Cargo</center></b></td>';
$html .= '       <td width="30%"><b><center>Salário</center></b></td>';
$html .= '   </tr>';

$html .= '   <tr>';
$html .= '       <td>01/12/2013</td>';
$html .= '       <td>JOAO DA SILVA</td>';
$html .= '       <td>SUPERVISOR(A) ATC</td>';
$html .= '       <td>1.165,00</td>';
$html .= '   </tr>';
$html .= '   <tr>';
$html .= '       <td>01/10/2010</td>';
$html .= '       <td>MARIA DO BAIRRO</td>';
$html .= '       <td>FERRAMENTEIRO</td>';
$html .= '       <td>852,00</td>';
$html .= '   </tr>';
$html .= '   <tr>';
$html .= '       <td>01/05/2015</td>';
$html .= '       <td>KARINA DE SOUZA</td>';
$html .= '       <td>AUX. ADMINISTRATIVO</td>';
$html .= '       <td>855,49</td>';
$html .= '   </tr>';
$html .= '</table>';

return $html;

Função para geração do XLS:

function geraXls($arquivo, $html){ 
    // Configurações header para forçar o download
    header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    header ("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
    header ("Cache-Control: no-cache, must-revalidate");
    header ("Pragma: no-cache");
    header ("Content-type: application/x-msexcel");
    header ("Content-Disposition: attachment; filename=\"$arquivo\"" );
    header ("Content-Description: PHP Generated Data" );
    // Envia o conteúdo do arquivo
}

No exemplo:
- 1.165,00 vai exportar para o excel certo;
- 852,00 não exporta correto, ou seja, exporta 852;
- 855,49, exporta correto também.

Alguém teria alguma ideia do que possa ser?
Para formatar já fiz essas duas formas mas não deram certo:

$salario = sprintf('%.2f', '852,00'); // ESTE TRANSFORMA O CAMPO EM STRING E NA HORA DE FAZER ALGUMA FORMULA NO EXCEL NÃO FUNCIONA
$salario = number_format('852,00', 2, ',', '.'); // ESTE FAZ O QUE FALEI NO EXEMPLO ACIMA.

Desde já, agradeço a ajuda de todos.

Apenas um detalhe. No codigo abaixo, se eu tiro o ponto, quando os valores são maiores que 1000, também não traz as decimais.
Ex:

$salario = number_format('1852,00', 2, ',', '.');

No codigo acima, o export traz correto no excel, ou seja, 1.852,00

$salario = number_format('1852,00', 2, ',', '');

Nesse exemplo, eu tirei o ponto, o que fica errado, ou seja, 1852

Bom dia, alguma ideia pessoal?

Como você está utilizando HTML, você pode fazer a formatação das células via CSS. Exemplo para o que você precisa:


<style>
   .num{
      mso-number-format: "0\,00";
   }
</style>
<table>
   <tr>
      <td class="num">512,29</td>
      <td>Valor exibido: 512,29</td>
   </tr>
   <tr>
      <td class="num">512,296</td>
      <td>Valor exibido: 512,30 (é arredondado para 2 casas decimais)</td>
   </tr>
   <tr>
      <td class="num">512,00</td>
      <td>Valor exibido: 512,00</td>
   </tr>
   <tr>
      <td class="num">512</td>
      <td>Valor exibido: 512,00</td>
   </tr>
</table>

Salve esse código com extensão .xls/.xlsx e abra no Excel para visualizar e fazer ajustes (acabei de testar no LibreOffice com sucesso).

Mais tipos de formatações pode ser visto neste site:
http://cosicimiento.blogspot.com.br/2008/11/styling-excel-cells-with-mso-number.html

(vou deixar uma cópia neste post para caso o site saia do ar…)

Styling Excel cells with mso-number-format
mso-number-format:“0” —> NO Decimals
mso-number-format:“0.000” —> 3 Decimals
mso-number-format:"#,##0.000" —> Comma with 3 dec
mso-number-format:“mm/dd/yy” —> Date7
mso-number-format:“mmmm\ d,\ yyyy” —> Date9
mso-number-format:“m/d/yy\ h:mm\ AM/PM” —> D -T AMPM
mso-number-format:“Short Date” —> 01/03/1998
mso-number-format:“Medium Date” —> 01-mar-98
mso-number-format:“d-mmm-yyyy” —> 01-mar-1998
mso-number-format:“Short Time” —> 5:16
mso-number-format:“Medium Time” —> 5:16 am
mso-number-format:“Long Time” —> 5:16:21:00
mso-number-format:“Percent” —> Percent - two decimals
mso-number-format:“0%” —> Percent - no decimals
mso-number-format:“0.E+00” —> Scientific Notation
mso-number-format:"@" —> Text
mso-number-format:"#\ ???/???" —> Fractions - up to 3 digits (312/943)
mso-number-format:"\0022£\0022#,##0.00" —> £12.76
mso-number-format:"#,##0.00_ ;[Red]-#,##0.00\ " —> 2 decimals, negative numbers in red and signed(1.56 -1.56)

Anderson, obrigado pela resposta.

Porém, não funcionou

Que estranho…
Como ficou seu código com as alterações?

Criei o estilo e chamei através da propriedade class na tag html. Tentei também colocando na propriedade style direto na linha do valor mas também sem sucesso. É o mesmo código acima com essas mudanças.

Qual software você está usando para visualizar o arquivo? Office/Excel? LibreOffice? OpenOffice? E qual a versão do software?

O exemplo de tabela que eu coloquei funcionou corretamente para você?
Testei hoje e para mim funcionou…

Excelente dica, Anderson. Isto vai me servir para um problema que tive aqui, na hora de formatar determinado campo no envio para o Excel.

Anderson, estou usando o Excel 2010. Pra mim não está funcionando. Já tentei até em PHP puro, como no exemplo abaixo. Mas não funciona:

<?php
/*
* Criando e exportando planilhas do Excel
* /
*/
// Definimos o nome do arquivo que será exportado
$arquivo = 'planilha.xls';
$vlr1 = '852.00';
$vlr2 = '1000.55';

$sl1 = (double)number_format($vlr1, 2, '.', '');
$sl2 = (double)number_format($vlr2, 2, '.', '');

// Criamos uma tabela HTML com o formato da planilha
$html = '';
$html .= '<table>';
$html .= '<tr>';
$html .= '<td colspan="3">Planilha teste</tr>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td><b>Coluna 1</b></td>';
$html .= '<td><b>Coluna 2</b></td>';
$html .= '<td><b>Coluna 3</b></td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td>L1C1</td>';
$html .= '<td>'.$sl1.'</td>';
$html .= '<td>'.$sl2.'</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td>L2C1</td>';
$html .= '<td>L2C2</td>';
$html .= '<td>L2C3</td>';
$html .= '</tr>';
$html .= '</table>';
// Configurações header para forçar o download
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
header ("Content-type: application/x-msexcel");
header ("Content-Disposition: attachment; filename=\"{$arquivo}\"" );
header ("Content-Description: PHP Generated Data" );
// Envia o conteúdo do arquivo
echo $html;
exit;

?>

Valeu!

Realmente, copiei e colei seu código e não funcionou como deveria. Mas vi que está sem o CSS que faz a formatação (esqueceu de colar ele aqui?), e também o valor que deve ficar no TD deve estar formatado com vírgula ao invés de ponto (assim: 852,00). Alterei seu exemplo e funcionou, ficou assim:

<?php
/*
* Criando e exportando planilhas do Excel
* /
*/
// Definimos o nome do arquivo que será exportado
$arquivo = 'planilha.xls';
$vlr1 = '852.00';
$vlr2 = '1000.55';




$sl1 = (double)number_format($vlr1, 2, ',', '');
$sl2 = (double)number_format($vlr2, 2, ',', '');




// Criamos uma tabela HTML com o formato da planilha
$html = '';
$html .= '<style>';
$html .= '.num{';
$html .= 'mso-number-format: "0\,00";';
$html .= '}';
$html .= '</style>';
$html .= '<table>';
$html .= '<tr>';
$html .= '<td colspan="3">Planilha teste</tr>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td><b>Coluna 1</b></td>';
$html .= '<td><b>Coluna 2</b></td>';
$html .= '<td><b>Coluna 3</b></td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td>L1C1</td>';
$html .= '<td class="num">'.$sl1.'</td>';
$html .= '<td class="num">'.$sl2.'</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td>L2C1</td>';
$html .= '<td>L2C2</td>';
$html .= '<td>L2C3</td>';
$html .= '</tr>';
$html .= '</table>';
// Configurações header para forçar o download
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
header ("Content-type: application/x-msexcel");
header ("Content-Disposition: attachment; filename=\"{$arquivo}\"" );
header ("Content-Description: PHP Generated Data" );
// Envia o conteúdo do arquivo
echo $html;
exit;
?>

Veja se com este exato código funciona para você…

Bom dia amigo!
Testei o mesmo código que vc informou acima mas sem sucesso. Testei em Chrome e Mozilla mas sem sucesso.

Realmente, testei o código no meu notebook em casa e não funcionou no Microsoft Office Excel.

Ainda tem outras alternativas… no LibreOffice funcionou, mas aqui no serviço não tenho acesso ao Microsoft Office Excel para testar.

(outra alternativa)

<table>
    <tr>
        <td x:num>512,29</td>
        <td sdnum="1046;0;#.##0,00">512,29</td>
        <td>Valor exibido: 512,29</td>
    </tr>
    <tr>
        <td x:num>512,296</td>
        <td sdnum="1046;0;#.##0,00">512,296</td>
        <td>Valor exibido: 512,30 (é arredondado para 2 casas decimais)</td>
    </tr>
    <tr>
        <td x:num>512,00</td>
        <td sdnum="1046;0;#.##0,00">512,00</td>
        <td>Valor exibido: 512,00</td>
    </tr>
    <tr>
        <td x:num>512</td>
        <td sdnum="1046;0;#.##0,00">512</td>
        <td>Valor exibido: 512,00</td>
    </tr>
</table>

Uma outra opção é usar o “Microsoft Office XML formats”:
https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
https://blogs.msdn.microsoft.com/brian_jones/2005/06/27/introduction-to-excel-xml-part-1-creating-a-simple-table/

<?xml version="1.0" encoding="UTF-8"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Styles>
        <Style ss:ID="titulo">
            <Font ss:FontName="Calibri" ss:Size="11" ss:Bold="1" ss:Color="#B22222"/>
            <Alignment ss:Horizontal="Center"/>
        </Style>
        <Style ss:ID="valor">
            <NumberFormat ss:Format="0.00"/>
            <Font ss:FontName="Calibri" ss:Size="11"/>
            <Alignment ss:Horizontal="Right"/>
        </Style>
        <Style ss:ID="geral">
            <Font ss:FontName="Calibri" ss:Size="11"/>
            <Alignment ss:Horizontal="Right"/>
        </Style>
    </Styles>
    <ss:Worksheet ss:Name="Planilha123456">
        <Table>
            <Column ss:StyleID="geral" ss:Width="90"/>
            <Column ss:StyleID="valor" ss:Width="100"/>
            <Column ss:StyleID="geral" ss:Width="90"/>
            <Row>
                <Cell ss:StyleID="titulo"><Data>Original</Data></Cell>
                <Cell ss:StyleID="titulo"><Data>Formatado</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">512.29</Data></Cell>
                <Cell><Data ss:Type="Number">512.29</Data></Cell>
                <Cell><Data>Exibe: 512,29</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">512.296</Data></Cell>
                <Cell><Data ss:Type="Number">512.296</Data></Cell>
                <Cell><Data>Exibe: 512,30</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">512</Data></Cell>
                <Cell><Data ss:Type="Number">512</Data></Cell>
                <Cell><Data>Exibe: 512,00</Data></Cell>
            </Row>
            <Row>
                <Cell><Data ss:Type="String">512</Data></Cell>
                <Cell><Data ss:Type="Number">512</Data></Cell>
                <Cell><Data>Exibe: 512,00</Data></Cell>
            </Row>
        </Table>
    </ss:Worksheet>
</Workbook>

obs: salvei os dois códigos com extensão “.xlsx” e ambos funcionaram no LibreOffice - não tenho o Excel para testar agora - e possivelmente funcionam no Excel também (pelo menos o código em XML é para funcionar, já que é da própria Microsoft)

Em último caso, você pode usar uma biblioteca como o PHPExcel (o resultado final não é HTML), nele tem funções para formatação de célula…