I am taking data from a form and saving it in a CSV file using PHP. My one field in the form contain the comma in it, i.e., between two words a comma is there and I need to store that in the CSV file with a comma. But when I an saving it the values left and right to comma are stored in different rows. How can I do it?
My code is:
enter code here
<?php
//read data from form
$food = filter_input(INPUT_POST, "food");
$output = $food . "\n";
$fp="input.csv";
if (file_exists($fp)) {
file_put_contents($fp, $output, FILE_APPEND);
}
else {
file_put_contents($fp, $output);
}
?>
By default, CSV files use the comma as the field separater, so if the value contains any commas, it needs to be quoted in the same way it should be if it contains spaces. If using "file_put_contents", you need to do that manually with something like this:
<?php
//read data from form
$food = filter_input(INPUT_POST, "food");
$output = preg_match('/[, ]/', $food) ? "\"$food\"\n" : "$food\n";
file_put_contents('input.csv', $output, FILE_APPEND);
?>
The "preg_match" function checks $food for commas or spaces and if any are found, $food is double quoted and the linefeed is added, otherwise only the linefeed is added.
Note also that you don't need to check if the file already exists, because if it doesn't, the file_put_contents function automatically creates it whether or not you use the FILE_APPEND flag.
But a much better solution would be to use the CSV specific functions which do any necessary quoting or escaping for you automatically:
<?php
//read data from form
$food = filter_input(INPUT_POST, "food");
$fields = array($food);
$fp = fopen('input.csv', 'a+');
fputcsv($fp, $fields);
fclose($fp);
?>
Using fopen in "a+" mode causes it to act the same as file_put_contents does with the FILE_APPEND flag. So there's no need to check if the file exists beforehand here either.
Related
So I have this code:
$datas .= '"' . implode('", "', $body["id"].",".$body["prefecture_id"].",".$body["industry_id"].",".$body["offset"].",".$body["name"].",".$email . ",".$body["tel"].",".$body["fax"].",".$body["address"].",".$body["address_coordinate"].",".$body["url"].",".$body["image_url"].",".$body["flexible_1"].",".$body["flexible_2"].",".$body["flexible_3"].",".$body["flexible_4"].",".$body["flexible_5"].",".$body["flexible_6"].",".$body["flexible_7"].",".$body["flexible_8"].",".$body["flexible_9"].",".$body["flexible_10"].",".$body["sequence"].",".$body["del_flg"].",".$body["create_date"].",".$body["create_user"].",".$body["update_date"].",".$body["update_user"]).'"'."\r\n";
I want it to look like this:
"KN01001","01","4","500","Starbuck's","admin#starbucks.com","09-232-821","09-232-822","Upper G/F SM, Juan Luna Extension"
Problem is address has comma, so this would separate it.
I really could not construct it right. Please help
this code is from a CSV convert function. In the CSV file each column is separated by a comma.
But my problem is that I have several columns that contains also comma. I would like that those commas in the columns remain as it is.
Instead of rolling your own CSV encoding function it might be better to use the built in fputcsv().
$out = fopen("php://memory", "w");
foreach($something as $body) {
fputcsv($out, $body);
}
rewind($out);
$data = stream_get_contents($out);
You'll need to adapt the code to order the columns if you want but that's the basic method (Don't forget to close $out either).
To save holding the entire CSV in memory (if this was a file download/export mechanism) you could open php://output instead and write/flush directly to the web-server/browser.
To answer your question directly implode() takes an array as a second argument but you've given it a string so change it to this (and add all the fields):
$datas .= '"' . implode('", "', [$body["id"], $body["prefecture_id"], $body["industry_id"], $body["offset"], ...]) . "\"\r\n";
can you use fgetcsv() instead of implode? This would handle the
$fileHandle = fopen("filename.csv", "r");
while (($row = fgetcsv($fileHandle, 0, ",")) !== FALSE) {
var_dump($row);
//$row is an array of all the columns in the csv regardless of commas in the dat
}
Otherwise if you must use implode, is the data that has a comma enclosed in speech marks: "some date, with a comma". If so you could use a regex to ignore the commas within the speechmarks. I can't see your data so its hard to say.
I am working on a PHP statement that runs a query and then writes the data to a .csv file. The problem I am having is that some of the data I am receiving from the server has commas in the data which causes for the .csv file to enter data in the wrong place. Below I have an example of the code.
$sql = "Select *
From table;"
$data = mysqli_query($link, $sql);
$row= ("Column One, Column Two, Column Three\n");
while ($result = $data->fetch_assoc()) {
$row .= ("$result[columnOne], $result[columnTwo], $result[columnThree]\n");
}
$fd = fopen("./filePath.csv", "w") or die ("Error Message");
fwrite($fd, $row);
fclose($fd);
Column three is where the data contains commas which causes for it to write to different cells in the .csv file. Is there any solution to make the $result[columnThree] data stay in one cell even though it contains commas in it?
You can wrap the values in double-quotes:
$row .= ('"'.$result['columnOne'].'", "'.$result['columnTwo'].'", "'.$result['columnThree'].'"\n"');
Instead of concatenating a string, I like to use arrays as much as possible:
$rawCsv = array();
while ($result = $data->fetch_assoc()) {
if (count($rawCsv) === 0)
$rawCsv[] = '"'.implode('","', array_keys($result )).'"';
$rawCsv[] = '"'.implode('","', $result ).'"';
}
$csvString = implode("\n", $rawCsv);
Both of these approaches will have a hard time with a different character in your data though -- the double quote. With that in mind, an even better alternative would be to use fopen and fputcsv to create your CSV data and you don't have to think about it.
If you plan to immediately offer the CSV data for download, you don't need a file at all, just dump it into the output butter:
ob_start();
$file_handle = fopen("php://output", 'w');
... if you do want to hang on to a file, then use fopen on the desired output file and skip the call to ob_start
Next, assemble your data:
fputcsv($file_handle, array(
'Your',
'headings',
'here'
));
while ($result = $data->fetch_assoc()) {
fputcsv($file_handle, array(
$result['Your'],
$result['data'],
$result['"here"']
));
}
fclose($file_handle);
... If you're using a file, then you're all set! If you are using the output buffer (no file used), you can grab the CSV data and send it to the browser directly:
$csv = ob_get_clean();
echo $csv; // should send headers first!
Be careful with output buffering, though, some frameworks/applications make use of it internally. If you're running in to problems with it, try using a file. If the file works, then your framework is probably already doing something with the output buffer.
Documentation
RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files - https://www.rfc-editor.org/rfc/rfc4180
implode - http://php.net/function.implode
fopen - http://php.net/manual/en/function.fopen.php
fclose - http://php.net/manual/en/function.fclose.php
fputcsv - http://php.net/manual/en/function.fputcsv.php
ob_start - http://php.net/manual/en/function.ob-start.php
ob_get_clean - http://php.net/manual/en/function.ob-get-clean.php
I'm trying to write some php-code that takes $_GET-data as an input and saves it into a csv-file.
When running the code more than once my csv-file looks like this:
Date,Time,Temperature,"Air Humidity","Soil Humidity",Light,"Wind Direction","Wind Speed",Rain
2013-03-16,16:24:27,12,80,40,82,255,10,0
"2013-03-16,16:24:26,12,80,40,82,255,10,0
","""2013-03-16,16:24:26,12,80,40,82,255,10,0
",""",""""""2013-03-16,16:24:25,12,80,40,82,255,10,0
",""","""""",""""
",""",""""""
","""
"
As you can see, the program adds quotation marks and commas into my data that I don't want. This is apparently done by 'file("weather_data.csv")' but I don't know how to disable or work around this.
This is my code for now:
<?php
// Save received data into variables:
$temperature = $_GET["t"];
$airHumidity = $_GET["ha"];
$soilHumidity = $_GET["hs"];
$light = $_GET["l"];
$windDir = $_GET["wd"];
$windSpeed = $_GET["ws"];
$rain = $_GET["r"];
// Arrays for the column descriptor (first line in the csv-file) and the recent data:
$columnDescriptor = array("Date","Time","Temperature","Air Humidity","Soil Humidity","Light","Wind Direction","Wind Speed","Rain");
$recentData = array(date("Y-m-d"),date("H:i:s"),$temperature,$airHumidity,$soilHumidity,$light,$windDir,$windSpeed,$rain);
$fileContents = file("weather_data.csv");
array_shift($fileContents); // removes first field of $fileContents
$file = fopen("weather_data.csv","w");
fputcsv($file,$columnDescriptor);
fputcsv($file,$recentData);
fputcsv($file,$fileContents);
fclose($file);
?>
$fileContents is read as an array of strings, one entry per line of the CSV file but the actual CSV data is not parsed. The last fputcsv tries to write this data as CSV and escapes it (adding quotes and stuff). You need to add the old file contents ($fileContents) to your file with fwrite instead of fputcsv:
fwrite($file, implode("\n", $fileContents));
I use the following code to get data from a form and save it as csv.
$cvsData = $name . "," . $address . "\n";
$fp = fopen("file.csv", "a");
if ($fp) {
fwrite($fp, $cvsData); // Write information to the file
fclose($fp); // Close the file
}
When someone enters a comma or line break in address field it breaks the formatting. So how can i escape it so that the whole address stays in the same field ?
Put each data item inside quotation marks. A pair of quotation marks inside a quoted value signifies a single quotation mark. e.g.
"Daniel Norton","Congress Ave.
Austin (""Keeping it weird""), TX"
Referring to your example:
$data = str_replace('"','""',$data);
$address = str_replace('"','""',$address);
$cvsData = "\"$data\",\"$address\"\n";
Better still, just use the PHP function fputcsv.
fputcsv($fp,array($data,$address));
CSV is totally dependent on the software used to read it.
Have a look at http://www.csvreader.com/csv_format.php for some details on how certain programs expect CSV data.
I have created a CSV class that can handle most of these situations. You might want to have a look at it.
https://gist.github.com/1786683
And to answer your question, using that class you could
$csv = CSV::newExcel();
$cvsData = $csv->row($name, $address);
// etc...
I'm creating a script that will read a csv file and display it on a textarea using fgetcsv.
$handle = #fopen($filePath, "r");
if ($handle)
{
while (($buffer = fgetcsv($handle, 1000,",")) !== false)
{
foreach($buffer as $buff){
echo $buff."\n";
}
}
}
The format of the csv is
"line1-content1","line1-content2"
"line2-content1","line2-content2"
Using fgetcsv, the content will display inside the textarea without double-quote and comma. Can I format it so that it will also display the duoble quotes and comma?
Then upon saving it using fputcsv
$file_to_load = $_GET['filepath'];
$filePath = $dir.$file_to_load;
$trans = trim($_POST['txtarea']);
$keyarr = split("\n",$trans);
$fp = fopen($filePath, 'w');
foreach (array ($keyarr) as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
Looking on the csv file, it saved the csv but displays it like this
"line1-content1
","line1-content2
","line2-content1
","line2-content2"
It separates the "line1-content1" and "line1-content2" into two lines and put a comma after the end of every line.
Now I want to keep the formatting of #2. How will I code it?
Can you guide me into the right direction? Thanks!
Sounds like you want to display the actual raw CSV text, not the parsed data within the CSV. Instead of using fgetcsv(), just use fgets() and you'll get the text line without any parsing, preserving the quotes and commas.
As for fputcsv, it's going to write out what you pass into it, so make sure that whatever's coming back from the form is cleaned up (e.g. extra line breaks stripped out).