i'm trying to read a lot of txt files and save the first line as a title, and the rest of text as a content, then export to a CSV file.
i create a id for CSV that increase by iteration, but when i have an error that i cant see in the iteration because when it save the content in the array add the last content to this value.
I need to create a CSV with 3 "columns" named, id, titulo and contenido and by each file, save in a array the information. One txt file, one iteration of array.
Sorry for my english.
this is my code:
<?php
/* Cogemos todos los archivos txt de la carpeta archivos del servidor */
$files = glob("archivos/*.txt");
/* Creamos el array para guardar los datos y le metemos la primera línea que es el nombre de los campos a importar */
$datosparacsv=array(array("ID","titulo","contenido"));
/* Creamos el id que tendrá cada campo del array para después poder importar */
$id = 0;
/* Recorremos cada archivo para coger los datos */
foreach($files as $file) {
/* Sacamos el título de la primera línea del archivo txt */
$titulo = trim(fgets(fopen($file, 'r')));
/* Sacamos el resto del contenido pero quitamos la primera linea con el condicional if*/
$archivo = file($file);
foreach ($archivo as $num=>$line){
if ($num==0) {
continue;
}
else{
$contenido .= $line."\n";
}
}
/* Añadimos el contenido extraido al array para luego pasarlo a CSV */
array_push($datosparacsv, array($id,$titulo,$contenido));
/* Sumamos uno al id para que sea único */
$id++;
}
$delimitador = ','; //parameter for fputcsv
$enclosure = '"'; //parameter for fputcsv
//convert array to csv
$archivocsv = fopen('entradas.csv', 'w+');
foreach ($datosparacsv as $data_line) {
fputcsv($archivocsv, $data_line, $delimitador, $enclosure);
}
$data_read="";
rewind($archivocsv);
//read CSV
while (!feof($archivocsv)) {
$data_read .= fread($archivocsv, 8192); // will return a string of all data separeted by commas.
}
fclose($archivocsv);
echo $data_read;
Example of files to read.
File 1.txt
Titulo 1
texto 1
File 2.txt
Titulo 2
texto 2
CSV
id, titulo, contenido, 0, Titulo 1, texto 1, 1, Titulo 2, texto 2
Thank you very much mates.
$contenido on line 19 is undefined and it's trying to concatenate a non-existent variable with .=. The $contenido variable also isn't required because each archive line is defined in $datosparacsv.
It's also unnecessary to define $delimitador and $enclosure because the defined values are also the default values.
Here's the correct PHP code with the expected CSV output with comments explaining each modified line.
It also preserves new lines and spaces in content as required.
<?php
/* Cogemos todos los archivos txt de la carpeta archivos del servidor */
$files = glob("archivos/*.txt");
/* Creamos el array para guardar los datos y le metemos la primera línea que es el nombre de los campos a importar */
$datosparacsv = array(
array(
"ID",
"titulo",
"contenido"
)
);
/* Creamos el id que tendrá cada campo del array para después poder importar */
$id = 0;
foreach($files as $file) {
/* Sacamos el resto del contenido pero quitamos la primera linea con el condicional if*/
$archivos = file($file);
// Remove and retrieve CSV heading values from each file with array_shift instead of a conditional in each $archivo iteration
$titulo = trim(array_shift($archivos));
// Append to the ID and title to the CSV data array with $datosparacsv[] instead of array_push() while incrementing the ID
$datosparacsv[$id + 1] = array(
$id++,
$titulo,
''
);
foreach ($archivos as $archivo) {
// Append each line from $archivos with preserved spaces and new lines
$datosparacsv[$id][2] .= $archivo;
}
// Trim leading and trailing whitespace
$datosparacsv[$id][2] = trim($datosparacsv[$id][2]);
}
$archivocsv = fopen('entradas.csv', 'w+');
foreach ($datosparacsv as $data_line) {
// Add the data to the CSV with the default delimiter and enclosure
fputcsv($archivocsv, $data_line);
}
?>
archivos/1.txt
Titulo 1
texto 1
archivos/2.txt
Titulo 2
texto 2
texto3
texto4
This saves entradas.csv with this data.
ID,titulo,contenido
0,"Titulo 1","texto 1"
1,"Titulo 2","texto 2
texto3
texto4"
i use this forme because i can format my anser better.
i need that the whole content of the file less the first line was in the column $contenido.
Now, with your code, works fine but if the same file has more than one line after content, it uses each line as a new line of the result.
For example i use now this files
Archivo 1.txt
Titulo 1
texto 1,texto 1
Some more text in file 1
Archivo 2.txt
Titulo 2
texto 2, texto 2, texto 2, texto 2, texto 2, texto 2
Some text 2 of the same archive
and this generates this entradas.csv
ID,titulo,contenido
0,"Titulo 1","texto 1,texto 1"
1,"Titulo 1",
2,"Titulo 1","Some more text in file 1"
3,"Titulo 2","texto 2, texto 2, texto 2, texto 2, texto 2, texto 2"
4,"Titulo 2",
5,"Titulo 2","Some text 2 of the same archive"
But i need that:
ID,titulo,contenido
0,"Titulo 1","texto 1,texto 1
Some more text in file 1"
1,"Titulo 2","texto 2, texto 2, texto 2, texto 2, texto 2, texto 2
Some text 2 of the same archive"
It's important that the contents saves all spaces and \n that they have in the txt file because this txt files are posts of a blog.
An example of one file.txt
¿Como puedo comer galletas?<-- Title
Las galletas se comen con la boca, poco a poco masticando.
<h2>¿Cuántos sabores de galletas hay?</h2>
Pues hay de todos los que puedas imaginar.
and all of this text after title have to stay in the same line saving \n and all.
One file only one line in the CSV.
thank you very much and im sorry for my english.
I am using PHP and fPDF to create a PDF "invoice" and everything works perfectly fine on the first page but when the table has to go to the second page it only returns the first value from the sql query and everything goes to the rest goes to the third page and so on.
This is the code that loops the table rows
$sql=sprintf("SELECT * FROM rostosativos_invoice where id_proposta = '".$_GET['id']."';");
$res=mysqli_query($link, $sql);
while ($r=mysqli_fetch_assoc($res)){
// produto = posição 5
// quantidade = posição 7
// precouni = posição 6
// soma = posição 9
//multicell
$cellWidth=120;//tamanho da cell
$cellHeight=6.5;//altura da cell
//verificar se o texto passa a cell
if($pdf->GetStringWidth($r['produto']) < $cellWidth){
//se não, não fazer nada
$line=1;
}else{
//~se estiver, ~então calcular a altura necessária para a cobrir a cell
//ao dividir o texto para ajustar ao tamanho da cell
//~depois contar quantas linhas são necessãrias para ajustar o texto na cell
$textLength=strlen($r['produto']); //total text length
$errMargin=10; //cell com margem de erro, just in case
$startChar=0; //posição inicial para cada linha
$maxChar=0; //Máxima caracteres numa linha, para incremetar mais tarde
$textArray=array(); //Guardar as strings em cada linha
$tmpString=""; //Guardar a string numa linha temporária
while($startChar < $textLength){ //loop até ao fim do texto
//loop até chegar ao máximo de caracteres
while(
$pdf->GetStringWidth( $tmpString ) < ($cellWidth-$errMargin) &&
($startChar+$maxChar) < $textLength ) {
$maxChar++;
$tmpString=substr($r['produto'],$startChar,$maxChar);
}
//mover startChar para a próxima linha
$startChar=$startChar+$maxChar;
//depois adicionar para o array para saber quantas linhas serão necessárias
array_push($textArray,$tmpString);
//reset maxChar e tmpString
$maxChar=0;
$tmpString='';
}
//receber o numero de linhas
$line=count($textArray);
}
//usar MultiCell em vez de Cell
//mas primeiro, como a MultiCell é sempre tratada como fim de linha, precisamos de
//definir manualmente a posição xy para a próxima cell ficar ao lado.
//guardar a posição x e y antes de escrever a multicell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
$pdf->MultiCell($cellWidth,$cellHeight,$r['produto'],1,'L');
//receber a posição para a próxima cell ao lado da multicell
//e equilibrar o x com o tamanho da multicell
$pdf->SetXY($xPos + $cellWidth , $yPos);
//escrever as cells
$pdf->Cell(15,($line * $cellHeight),$r['quantidade'],1,0); //adaptar a altura ao número de linhas
$pdf->Cell(10,($line * $cellHeight),'UNI',1,0); //adaptar a altura ao número de linhas
$pdf->Cell(25,($line * $cellHeight),$r['precouni'].chr(128),1,0); //adaptar a altura ao número de linhas
$pdf->Cell(25,($line * $cellHeight),$r['soma'].chr(128),1,1); //adaptar a altura ao número de linhas
}
This is the full PHP code:
class PDF extends TFPDF {
// Page Header
function Header() {
require("../config.php");
$rows = mysqli_query($link, "SELECT * FROM rostosativos_invoice INNER JOIN rostosativos_empresas ON rostosativos_invoice.empresa = rostosativos_empresas.empresa where id_proposta ='".$_GET['id']."';");
$r = mysqli_fetch_assoc($rows);
$id_empresa = $r['id_empresa'];
$idproposta = $r['id_proposta'];
$responsavel = $r['responsavel'];
$empresa = $r['empresa'];
$data = $r['data_registo'];
$contribuinte = $r['contribuinte'];
$assunto = $r['assunto'];
$refcliente = $r['refcliente'];
// Logo
$this->SetY(4);
$this->Image('../logo.png',10,6,30);
// Arial bold 15
$this->SetFont('Arial','B',9);
// Move to the right
$this->Cell(90);
// Title
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','Sede: Rua Azenha dos Latoeiros, 1-A || 2580-557 Ribafria '),'LTR',0,'C');
$this->Ln(5);
$this->Cell(90);
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','Oficina: Estrada Nacional nº1 km 33.3'),'LR',0,'C');
$this->Ln(5);
$this->Cell(90);
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','Quinta do Chacão, Casal Machado 2580-364 Alenquer '),'LR',0,'C');
$this->Ln(5);
$this->Cell(90);
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','E-mail: geral#rostosativos.com'),'LR',0,'C');
$this->Ln(5);
$this->Cell(90);
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','www.rostosativos.com'),'LR',0,'C');
$this->Ln(5);
$this->Cell(90);
$this->Cell(100,10,iconv('UTF-8', 'windows-1252','www.facebook.com/rostosativos/'),'LBR',0,'C');
// Line break
$this->SetFont('Arial','',12);
$this->Ln(15);
$this->Cell(100 ,5,'',0,0);
$this->Cell(35 ,5,'Proposta: ',0,0);
$this->Cell(34 ,5, $idproposta,0,1);//end of line
$this->Cell(100 ,5,'',0,0);
$this->Cell(35 ,5,iconv('UTF-8', 'windows-1252','Ref. Cliente: '),0,0);
$this->Cell(34 ,5,$refcliente,0,1);//end of line
$this->Cell(100 ,5,'',0,0);
$this->Cell(35 ,5,iconv('UTF-8', 'windows-1252','N.º Contribuinte: '),0,0);
$this->Cell(34 ,5,$contribuinte,0,1);//end of line
$this->Cell(100 ,5,'',0,0);
$this->Cell(35 ,5,'Data: ',0,0);
$this->Cell(34 ,5,$data,0,1);//end of line
$this->Ln(5);
//billing address
$this->Cell(100 ,5,'Proposta para:',0,0);//end of line
$this->Cell(100 ,5,'Assunto da proposta:',0,1);//end of line
//add dummy cell at beginning of each line for indentation
$this->Cell(10 ,5,'',0,0);
$this->Cell(90 ,5,iconv('UTF-8', 'windows-1252',$empresa),0,0);
$this->Cell(10 ,5,'',0,0);
$this->Cell(90 ,5,iconv('UTF-8', 'windows-1252',$assunto),0,1);
$this->Cell(10 ,5,'',0,0);
$this->Cell(90 ,5,iconv('UTF-8', 'windows-1252',$responsavel),0,1);
$this->Ln(2);
//invoice contents
$this->SetFont('Arial','B',12);
$this->Cell(120 ,6.5,iconv('UTF-8', 'windows-1252','Designação'),1,0);
$this->Cell(15 ,6.5,'Qtd.',1,0);
$this->Cell(10 ,6.5,'UNI',1,0);
$this->Cell(25, 6.5,iconv('UTF-8', 'windows-1252','Preço UNI.'),1,0);
$this->Cell(25 ,6.5,'Total',1,1);//end of line
}
function Footer() {
require("../config.php");
//~Tabela de Preço, etc..
$this->SetY(-20);
$sql=sprintf("SELECT * FROM rostosativos_invoice where id_proposta = '".$_GET['id']."' ORDER BY id DESC LIMIT 1;");
$res=mysqli_query($link, $sql);
while ($r=mysqli_fetch_assoc($res)){
$this->SetFont('Arial','',9);
$this->Cell(30, 6,iconv('UTF-8', 'windows-1252','Exclusões:'),0,0);
$this->Cell(15);
$this->Cell(65 ,6,'',0,0);
$this->SetFont('Arial','',11);
$this->Cell(40 ,6,iconv('UTF-8', 'windows-1252','Soma'),0,0);
$this->Cell(15);
$this->Cell(30, 6, $r['totalsoma'].chr(128),1,1,'R');
$this->SetFont('Arial','',9);
$this->Cell(30,6,iconv('UTF-8', 'windows-1252',$r['exclusao1']),0, 'L');
$this->SetFont('Arial','',11);
$this->Cell(15);
$this->Cell(65 ,6,'',0,0);
$this->Cell(40 ,6,iconv('UTF-8', 'windows-1252','Mão de Obra'),0,0);
$this->Cell(15);
$this->Cell(30, 6, $r['maoobra'].chr(128),1,1,'R');
$this->SetFont('Arial','',9);
$this->Cell(30,6,iconv('UTF-8', 'windows-1252',$r['exclusao2']),0, 'L');
$this->SetFont('Arial','',11);
$this->Cell(80 ,6,'',0,0);
$this->Cell(40 ,6,'Valor GLOBAL em EUROS',0,0);
$this->Cell(15);
$this->Cell(30 ,6,$r['precototal'].chr(128),1,1,'R');//end of line
}
// Position at 1.5 cm from bottom
$this->SetY(-9);
// Arial italic 8
$this->SetFont('Arial','I',8);
// Page number
$this->Cell(0,10,iconv('UTF-8', 'windows-1252','Página '.$this->PageNo().'/{nb}'),0,0,'C');
}
}
//A4 width : 219mm
//default margin : 10mm each side
//writable horizontal : 219-(10*2)=189mm
//create pdf object
$pdf = new PDF('P','mm','A4');
$pdf -> AliasNbPages();
//add new page
$pdf->AddPage();
// Add a Unicode font (uses UTF-8)
$pdf->AddFont('DejaVu','','DejaVuSansCondensed.ttf',true);
$pdf->SetFont('DejaVu','',12);
//set font to arial, regular, 12pt
$pdf->SetFont('Arial','',12);
$sql=sprintf("SELECT * FROM rostosativos_invoice where id_proposta = '".$_GET['id']."';");
$res=mysqli_query($link, $sql);
while ($r=mysqli_fetch_assoc($res)){
// produto = posição 5
// quantidade = posição 7
// precouni = posição 6
// soma = posição 9
//multicell
$cellWidth=120;//tamanho da cell
$cellHeight=6.5;//altura da cell
//verificar se o texto passa a cell
if($pdf->GetStringWidth($r['produto']) < $cellWidth){
//se não, não fazer nada
$line=1;
}else{
//~se estiver, ~então calcular a altura necessária para a cobrir a cell
//ao dividir o texto para ajustar ao tamanho da cell
//~depois contar quantas linhas são necessãrias para ajustar o texto na cell
$textLength=strlen($r['produto']); //total text length
$errMargin=10; //cell com margem de erro, just in case
$startChar=0; //posição inicial para cada linha
$maxChar=0; //Máxima caracteres numa linha, para incremetar mais tarde
$textArray=array(); //Guardar as strings em cada linha
$tmpString=""; //Guardar a string numa linha temporária
while($startChar < $textLength){ //loop até ao fim do texto
//loop até chegar ao máximo de caracteres
while(
$pdf->GetStringWidth( $tmpString ) < ($cellWidth-$errMargin) &&
($startChar+$maxChar) < $textLength ) {
$maxChar++;
$tmpString=substr($r['produto'],$startChar,$maxChar);
}
//mover startChar para a próxima linha
$startChar=$startChar+$maxChar;
//depois adicionar para o array para saber quantas linhas serão necessárias
array_push($textArray,$tmpString);
//reset maxChar e tmpString
$maxChar=0;
$tmpString='';
}
//receber o numero de linhas
$line=count($textArray);
}
//usar MultiCell em vez de Cell
//mas primeiro, como a MultiCell é sempre tratada como fim de linha, precisamos de
//definir manualmente a posição xy para a próxima cell ficar ao lado.
//guardar a posição x e y antes de escrever a multicell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
$pdf->MultiCell($cellWidth,$cellHeight,$r['produto'],1,'L');
//receber a posição para a próxima cell ao lado da multicell
//e equilibrar o x com o tamanho da multicell
$pdf->SetXY($xPos + $cellWidth , $yPos);
//escrever as cells
$pdf->Cell(15,($line * $cellHeight),$r['quantidade'],1,0); //adaptar a altura ao número de linhas
$pdf->Cell(10,($line * $cellHeight),'UNI',1,0); //adaptar a altura ao número de linhas
$pdf->Cell(25,($line * $cellHeight),$r['precouni'].chr(128),1,0); //adaptar a altura ao número de linhas
$pdf->Cell(25,($line * $cellHeight),$r['soma'].chr(128),1,1); //adaptar a altura ao número de linhas
}
//output the result
$pdf->Output();
$content = $pdf->Output('propostas/'.$_GET['id'].'.pdf','F');
file_put_contents($content);
Make these changes right after you define the PDF and pages.
$pdf = new PDF('P','mm','A4');
$pdf -> AliasNbPages();
$pdf->AddPage();
$pdf->SetAutoPageBreak(false); // add this line and the next
$howhigh = $pdf->GetPageHeight(); // stash the height of the page for later
The next change is in the else where the size of the larger cells is calculated. There is really no reason to go through the data to be added character by character. You can replace that block of code with:
//verificar se o texto passa a cell
if ($pdf->GetStringWidth($r['produto']) < $cellWidth) {
//se não, não fazer nada
$line=1;
} else {
$line = ceil($pdf->GetStringWidth($item[2]));
$line = round($line / $cellWidth,0) + 1;
}
Finally, the actual output of the data needs a little change to account for testing whether or not we need to start a new page. As you'll see the calculation done above are used.
//usar MultiCell em vez de Cell
//mas primeiro, como a MultiCell é sempre tratada como fim de linha, precisamos de
//definir manualmente a posição xy para a próxima cell ficar ao lado.
//guardar a posição x e y antes de escrever a multicell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
$total = $yPos + (($line * $cellHeight));
if ($total > $howhigh) { // we will spill to a new page with this cell
$pdf->AddPage(); // so start a new page before we add the cell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
}
$pdf->MultiCell($cellWidth,$cellHeight,$r['produto'],1,'L');
//receber a posição para a próxima cell ao lado da multicell
//e equilibrar o x com o tamanho da multicell
$pdf->SetXY($xPos + $cellWidth , $yPos);