Generate CSV with side-by-side results in PHP

Asked

Viewed 460 times

3

I’m trying to get comparative results on a CSV generated in the php but I can’t stack side by side the way EXPECTED RESULT of the attached image.

I made a code below that did not break the line when it changes to 2018

TABLE

CREATE TABLE `clientes_vendas` (
  `codigo` int(11) NOT NULL,
  `cliente_cnpj` varchar(40) NOT NULL,
  `codigo_cliente` int(11) NOT NULL,
  `codigo_repre` int(11) NOT NULL,
  `valor` decimal(10,2) NOT NULL DEFAULT '0.00',
  `dia` varchar(20) NOT NULL,
  `mes` varchar(40) NOT NULL,
  `ano` varchar(40) NOT NULL,
  `data` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CODE

while:                         

  if ($ano_atual2==0) {
      $ano_atual2 = $ano;
  }  
  $pula_linha="\n";

  if ( $ano != $ano_atual2 )  :
      $ano_atual2 = $ano;
      $dadosTXT2 = "$pula_linha$nome_repre;$mes;$ano$pula_linha";
      $arraDados[] = $dadosTXT2;
      $soma=0;
  endif;

   @$soma +=  $row['valor'];
   $somaConvert = number_format($soma,2,",",".");
   $dadosTXT2 = "$cnpj_cliente;$nome_cliente;$nome_repre;$mes;$ano;$valor$pula_linha";
   $arraDados[] = $dadosTXT2;

endwhile; 

$fp = fopen($csv, 'a');
$escreve1 = fwrite($fp,   utf8_decode($header));

foreach ($arraDados as $file) {
    $escreve2 = fwrite($fp,  $file);
}

fclose($fp);

EXPECTED RESULT: Display SUMS of customer sales side by side EXAMPLE: AUGUST 2017 , AUGUST 2018, SEPTEMBER 2017- SEPTEMBER 2018 but starting normally from January

inserir a descrição da imagem aqui

  • 1

    all clients have unique cnpjs or can repeat themselves? or is there another unique id index in your table?

  • only the code is unique Anthraxisbr

  • 1

    What I don’t understand is that in the image of the expected result shows, IN THE SAME LINE => 1, 2017, valor - 1, 2018, valor - 2, 2017, valor. Is that what you want? Because?

  • 1

    What is the relationship? I don’t understand. O primeiro é o mês de janeiro de 2017, depois é janeiro 2018 e depois é fevereiro de 2017. A logo abaixo começa com janeiro de 2017, depois janeiro de 2018(outro valor), e fevereiro de 2018.

  • 1

    @Have you ever thought about doing a treatment similar to what you are doing this year? the code is unique per client,code will start at zero,in the 1st interaction makes the completion of the 1st line with the information for ex: $line=$cnpj_client;...;$mes;$year;$value; in the next interaction if the code is equal you continue concatenating only the month data,year, value, $line.= $mes;$ano;$valor; and so it goes, until a different code comes, with that $line .= $pular_line and stores in the output array.start $line again, updating the code ,putting the "header" as in the first interaction and etc..

  • 1

    @Andreicoelho Coelho I edited the image that was not clear ! the header doesn’t just need the results

  • 1

    Now I understand!

  • I will analyze @Marcusitalo Italo thank you.

Show 3 more comments

2 answers

4

$codigo_cliente = 0;
$pula_linha="\n";
while:                         

  if ($ano_atual2==0) {
      $ano_atual2 = $ano;
  }
  if ( $ano != $ano_atual2 )  :
      $ano_atual2 = $ano;
      $dadosTXT2 = "$pula_linha$nome_repre;$mes;$ano$pula_linha";
      $arraDados[] = $dadosTXT2;
      $soma=0;
  endif;

  if ($codigo_cliente == 0) {
      $codigo_cliente  = $row['codigo'];
      $linha = "$cnpj_cliente;$nome_cliente;$nome_repre;";
  }

  @$soma +=  $row['valor'];
   $somaConvert = number_format($soma,2,",",".");

  if ( $row['codigo']!= $codigo_cliente)  {
       $codigo_cliente  = $row['codigo'];
       $linha .= $pula_linha;
       $arraDados[] = $linha;
       $linha = "$cnpj_cliente;$nome_cliente;$nome_repre;$mes;$ano;$valor";
  }
  else{
    $linha .= "$mes;$ano;$valor;";
  }

endwhile; 

$fp = fopen($csv, 'a');
$escreve1 = fwrite($fp,   utf8_decode($header));

foreach ($arraDados as $file) {
    $escreve2 = fwrite($fp,  $file);
}

fclose($fp);

I hope I’ve helped or at least come close.

  • 1

    +1 for taking the $pula_linha of the loop

  • 4

    A tip: why instead of doing all this work at hand, you don’t use the function fputcsv?

3


To answer your question I had to create other tables that were not informed to get the nome_representante and the nome_cliente. And to do tests I created several records, see:

inserir a descrição da imagem aqui

I put as optional the input value of the beginning of the year and the end of the year to be analyzed, because you may want to perform a filter. See the line below:

$anoInicio = "2017";
$anoFim = "2018";

Finally, I created the code based on yours. Note that select is ordering, first by month, then by client code and then by year. This way you will get the expected result.

    $anoInicio = "2017";
    $anoFim = "2018";

    $query = mysqli_query($conn, "SELECT ano, mes, 
        (
            SELECT nome_cliente FROM cliente 
            WHERE cliente.codigo_cliente = clientes_vendas.codigo_cliente 
        ) AS 'nome_cliente', 
        (
            SELECT nome_representante FROM representante 
            WHERE representante.codigo_representante = clientes_vendas.codigo_representante 
            GROUP BY representante.codigo_representante
        ) AS 'nome_representante', 
        SUM(valor) AS 'total' FROM clientes_vendas 
        WHERE ano >= '$anoInicio' AND ano <= '$anoFim' 
        GROUP BY mes, codigo_cliente, ano ORDER BY codigo_cliente, mes, ano ASC"
        );

    $arraDados = array();
    $strTmpCliente = "";
    $mes = array('', 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'); // formatador dos meses
    $x = 1;


    while($dados = mysqli_fetch_assoc($query)){

        if($strTmpCliente != $dados['nome_cliente']){
            $strTmpCliente = $dados['nome_cliente'];
            $arraDados[$strTmpCliente] = array();
            $arraDados[$strTmpCliente]['nome'] = $dados['nome_cliente'];
            $arraDados[$strTmpCliente]['representante'] = $dados['nome_representante'];
        }

        $strMesAno = $mes[$dados['mes']]."_".$dados['ano'];
        $arraDados[$strTmpCliente][$strMesAno] = number_format($dados['total'],2,",",".");

    }


    $header = "Cliente;Representante;";
    $mesAtual = 1;
    $anoAtual = (int)$anoInicio;

    $arrayDatas = array();

    for($x = 0; $x < 24; $x++){

        $data = $mes[$mesAtual]."_".$anoAtual;
        $arrayDatas[] = $data;
        $header .= str_replace("_", "'",$data).";";

        $alteraMes = $x % 2 == 0 ? false : true;
        if($alteraMes){
            $mesAtual++;
            $anoAtual = $anoInicio;
            continue;
        }
        $anoAtual = $anoFim;
    }
    $header = substr($header, 0, -1);
    $header .= "\n";

    $strDados = array();

    foreach($arraDados as $cliente ){

        $strTmp = $cliente['nome'].";".$cliente['representante'].";";
        for($i = 0; $i < count($arrayDatas); $i++){
            $data = $arrayDatas[$i];
            if(isset($cliente[$data])){
                $strTmp .= $cliente[$data].";";
                continue;
            }
            $strTmp .= "-;";
        }

        $strTmp = substr($strTmp, 0, -1);
        $strTmp .= "\n";
        $strDados[] = $strTmp;

    }

    $csv = "arquivo.csv";

    // escreve o cabeçalho
    $fp1 = fopen($csv, 'w');
    fwrite($fp1, $header);
    fclose($fp1);

    // escreve o resultado
    $fp2 = fopen($csv, 'a');
    foreach ($strDados as $file) {
        fwrite($fp2,  $file);
    }
    fclose($fp2);

The generated file was like this:

inserir a descrição da imagem aqui

EDIT

I noticed that in the image that you posted that a few months were without sales. I went to take the test in my code and, as I imagined, it was a mistake. Because the values were filled sequentially.

I changed the code and now it is working correctly. I took the opportunity to insert the number_format that you are using. The result was this:

inserir a descrição da imagem aqui

EDIT 2

Change that part that will work:

           if($strTmpCliente != $dados['nome_cliente']){
                $strTmpCliente = $dados['nome_cliente'];
                $arraDados[$strTmpCliente] = array();
                $arraDados[$strTmpCliente]['nome'] = $dados['nome_cliente'];
                $arraDados[$strTmpCliente]['representante'] = $dados['nome_representante'];
            }

            //---> o erro estava aqui
            $dadosMes = (int)$dados['mes']; // aqui ele transforma em inteiro 
            $strMesAno = $mes[$dadosMes]."_".$dados['ano']; // aqui ele grava a strinmg corretamente
            $arraDados[$strTmpCliente][$strMesAno] = number_format($dados['total'],2,",",".");
  • apparently your code worked but only starts to fill the values after Oct'2017 and there are sales in the previous months, I’m analyzing to see I find why I return!

  • I think because in my table the months are recorded in VARCHAR and with 0 type 01,02,03 and its variable is $mesAtual =1 I am checking .....

  • check out ! @Andreicoelho https://codeshare.io/aJAJMK

  • changed to $mesAtual = '01'; and started picking from JAN'2017 and JAN'2018 then already jumps to Oct'2017 again ... updated link with the other two tables that are only to get the names https://codeshare.io/aJAJMK

  • 1

    @may be... I’ll do other tests.

  • 1

    @This was exactly the error. I just changed it. It’s in EDIT 2

  • @Denis succeeded?

  • 1

    I got it was formatting for whole ! Reply perfect Thank you very much !

  • 1

    @Don’t worry! Hug!

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.