Proper way to use PHP fputcsv function to export CSV file - php

What I want to do is, to export some dataset for Excel without using extra, 3rd party, heavy libraries.
The problem is, when I export the file, first row looks well, but starting from second row, it puts all $row data into first field of current row.
So I get file with first row properly placed in right columns and starting from second row instead of columns I see whole text in first field seperated by delimiter (comma)
Here is code snippet that I use for result.
$counter=0;
$file = fopen("sample.csv", "w");
foreach ($registrants as $registrant) {
$row = [
'Fullname' => $registrant->fullname,
'Phone' => $registrant->phone,
'Email' => $registrant->email,
];
if ($counter == 0)
fputcsv($file, array_keys($row));
fputcsv($file, $row);
$counter++;
}
fclose($file);
Also tried to
fputcsv($file, array_values($row), ';', ' ');
No success. What am I doing wrong? What is proper way to see correct result on all Excel versions regardless of OS or Excel locale and etc.?

Related

How to exclude the first line from a text file using php

My text file sample.txt. I want to exclude the first row from the text file and store the other rows into mysql database.
ID Name EMail
1 Siva xyz#gmail.com
2 vinoth xxx#gmail.com
3 ashwin yyy#gmail.com
Now I want to read this data from the text file except the first row(ID,name,email) and store into the MYsql db.Because already I have created a filed in database with the same name.
I have tried
$handle = #fopen($filename, "r"); //read line one by one
while (!feof($handle)) // Loop till end of file.
{
$buffer = fgets($handle, 4096); // Read a line.
}
print_r($buffer); // It shows all the text.
Please let me know how to do this?
Thanks.
Regards,
Siva R
It's easier if you use file() since it will get all rows in an array instead:
// Get all rows in an array (and tell file not to include the trailing new lines
$rows = file($filename, FILE_IGNORE_NEW_LINES);
// Remove the first element (first row) from the array
array_shift($rows);
// Now do what you want with the rest
foreach ($rows as $lineNumber => $row) {
// do something cool with the row data
}
If you want to get it all as a string again, without the first row, just implode it with a new line as glue:
// The rows still contain the line break, since we only trimmed the copy
$content = implode("\n", $rows);
Note: As #Don'tPanic pointed out in his comment, using file() is simple and easy but not advisable if the original file is large, since it will read the whole thing into memory as an array (and arrays take more memory than strings). He also correctly recommended the FILE_IGNORE_NEW_LINES-flag, just so you know :-)
You can just call fgets once before your while loop to get the header row out of the way.
$firstline = fgets($handle, 4096);
while (!feof($handle)) // Loop till end of file.
{ ...

How to split csv data in two parts.?

Is it possible to export csv data in to two parts:
From the below image i have two things to be considered
1. summery
2. Detail information
I worked with only 2nd type is it possible to do like 2 batches(like shown in image)..?
please suggest any alternate idea if you got.
Example:
summary header
$titleSummery = array('Course Name','Average watched','semi watched','notwached','sudents attempted','sudents notattempted','Total students','Branch','passout');
/*summery data */
Details header
$titleDetail = array('student','passout','branch','percentage watched','student email');
/*Details data */
In this case how can i export the data..?
$output = fopen('php://output', 'w');
fputcsv($output, $title);
foreach($data as $k=>$res){
fputcsv($output,$res);
}
You need to prepare array for each line. see my inline comments.
$titleSummery = array('Course Name','Average watched','semi watched','notwached','sudents attempted','sudents notattempted','Total students','Branch','passout');
$titleSummeryData = array('Number System','50%','40%',....); // fill remaining data.
$output = fopen('php://output', 'w');
// put first table
foreach($titleSummery as $key=>$val){
fputcsv($output,array($val,$titleSummeryData[$key]));
}
// begin second table
// put all title/header
fputcsv($output,$titleDetail);
// For second table i assume that you have data in 2D array
foreach($titleDetailsData as $row){
fputcsv($output);
}
fclose($output);
You direction is good, you just need to understand that each call to fputcsv prints a line, so you'll need to call it for each row in the first batch of data also, for example:
fputcsv($output,"course name","php for dummies");

How to filter on a word in a specific column of a csv file with PHP

I'm trying to display only the rows that contain a specific word in a specific column. Basically I would like to show only the rows that have "yes" in the Display column.
First_Name, Last_Name, Display
Kevin, Smith, yes
Jack, White, yes
Joe, Schmo, no
I've been trying various things with fgetcsv & str_getcsv from other answers and from php.net but nothing is working so far.
It doesn't do anything but this is my current code:
$csv = fopen('file.csv', 'r');
$array = fgetcsv($csv);
foreach ($array as $result) {
if ($array[2] == "yes") {
print ($result);
}
}
Let's have a look at the documentation for fgetcsv():
Gets line from file pointer and parse for CSV fields
fgetcsv reads a single line, not the whole file. You can keep reading lines until you reach the end of the file by putting it in a while loop, e.g.
<?php
$csv = fopen('file.csv', 'r');
// Keep looping as long as we get a new $row
while ($row = fgetcsv($csv)) {
if ($row[2] == "yes") {
// We can't just echo $row because it's an array
//
// Instead, let's join the fields with a comma
echo implode(',', $row);
echo "\n";
}
}
// Don't forget to close the file!
fclose($csv);
You should use data tables.
https://datatables.net/examples/basic_init/zero_configuration.html
That's how I deal with my textfiles. But be carefull, with a large amount of Data (> 10000 rows) you should have a loog at the deferRender option.
https://datatables.net/reference/option/deferRender <-- JSON DATA required.

PHP - Update specific row in CSV file

Is there an effective way to update/delete specific row in CSV file? Every other method included reading contents of entire file, creating temporary file and then replacing old file with it, etc...
But let's say, I have big CSV with 10000 records, so this kind of solution would be rather resource-heavy.
Let's say, I am unable to use database, so writing to file is the only way of storing data.
So, the question is, what would be the most effective way to do it?
Thank you in advance!
You're going to have to read the entire file. Sorry, no way around that. A CSV is a single, flat, text file with randomly sized fields and rows.
You definitely shouldn't be working directly with a CSV for database operations. You ought to pull the data into a database to work with it, then output it back to CSV when you're done.
You don't mention why you can't use a database, so I'm going to guess it's a resource issue, and you also don't say why you don't want to rewrite the file, so I'm going to guess it's due to performance. You could cache a number of operations and perform them all at once, but you're not going to get away from rewriting all or at least some portion of the file.
Consider reading the csv line by line into a multi-dimensional array, and at a certain row make your changes. Then, export array data out to csv. Below example modifies the 100th row assuming a 6-column comma delimited csv file (0-5).
Now, if you want to delete the row, then exclude it from $newdata array by conditionally skipping to next loop iteration with continue. Alternatively, if you want to update, simple set current inner array $newdata[$i] to new values:
$i = 0;
$newdata = [];
$handle = fopen("OldFile.csv", "r");
// READ CSV
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// UPDATE 100TH ROW DATA (TO EXCLUDE, KEEP ONLY $i++ AND continue)
if ($i == 99) {
$newdata[$i][] = somenewvalue;
$newdata[$i][] = somenewvalue;
$newdata[$i][] = somenewvalue;
$newdata[$i][] = somenewvalue;
$newdata[$i][] = somenewvalue;
$newdata[$i][] = somenewvalue;
$i++;
continue;
}
$newdata[$i][] = $data[0];
$newdata[$i][] = $data[1];
$newdata[$i][] = $data[2];
$newdata[$i][] = $data[3];
$newdata[$i][] = $data[4];
$newdata[$i][] = $data[5];
$i++;
}
// EXPORT CSV
$fp = fopen('NewFile.csv', 'w');
foreach ($newdata as $rows) {
fputcsv($fp, $rows);
}
fclose($fp);
Break the CSV into multiple files all in one directory.
That way you still have to rewrite files, but you don't have to rewrite nearly as much.
Bit late but for people who may search same thing, you could put your csv into an sqlite what addionaly gives you the ability to search in the dataset. There is some sample code: Import CSV File into a SQLite Database via PHP

Write 2 columns in a csv file from an array

I'm trying to write in 2 differents columns in a csv file but everything I've found set all the values in the first column with a separator.
Here is a small modification of the script example on php.net
<?php
$list = array (
['City', 'Country'],
['Brussels', 'Belgium'],
['Paris', 'France'],
['Berlin', 'Germany']
);
$fp = fopen('file.csv', 'w');
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
?>
And here is my csv file (I use Excel)
My question: is it possible to have the cities in A column and the countries in B column?
Thanks you for your help
You need to tell your spreadsheet program that the columns are separated by commas.
You will probably get the option to nominate a delimiter on opening the file.
I think you also have an option on a column - something like "Text to columns"
You can tell fputcsv() to use a different string as the delimiter instead of comma. This will use TAB, which is probably Excel's default:
fputcsv($fp, $fields, "\t");

Categories