Trying to build a .csv file in php from an array - php

I am trying to convert the following array into a .csv file where the questions will be on the first row and the corresponding answers in the second row and at the beginning a Timestamp should be there along with the time.
I have tried in the following way:
<?php
$qna = [
[
"questionNo"=> 1,
"question"=> "I am the life of the party.",
"answer"=> 2
],
[
"questionNo"=> 2,
"question"=> "I feel little concern for others.",
"answer"=> 4
],
[
"questionNo"=> 3,
"question"=> "I am always prepared.",
"answer"=> 2
],
[
"questionNo"=> 4,
"question"=> "I get stressed out easily.",
"answer"=> 4
]
];
$csv = '/home/ankur/Desktop/iq_data.csv';
$fp = fopen( $csv , 'w' );
$questionarray = array();
$answerarray = array();
$keyarray = array();
$valuearray = array();
foreach( $qna as $key => $questions) {
$questionarray[] = $questions['question'];
$answerarray[] = $questions['answer'];
}
$keyarray[] = "Timestamp";
$valuearray[] = time();
$row = array();
array_push($row,$keyarray);
array_push($row,$valuearray);
array_push($row,$questionarray);
array_push($row,$answerarray);
for($i=0; $i < count($row); $i++) {
fputcsv($fp, $row[$i] );
}
fclose( $fp );
?>
It is creating the .csv file but the timestamp and its value is not in the same row as that of the question answer as follows:
Timestamp
1676484864
I am the life of the party. I feel little concern for others. I am always prepared. I get stressed out easily.
2 4 2 4
I want that the Timestamp column to be in the same row as that of the questions as follows:
Timestamp I find it hard to imitate the behavior of other people. My behavior is usually an expression of my true inner feelings, attitudes, and beliefs.
12/3/21 14:05 TRUE TRUE
Kindly suggest if possible where am I doing it incorrectly.

You only need two lines to be inserted in your csv file, so you only need to loop the $qna array to populate two flat arrays.
You can prepopulate the first element of the first array with the static word "Timestamp" and the first element of the second array with the current unix time.
Then you loop over the $qna array to push questions and answers into their respective arrays. I am using a body-less loop, but you can perform the pushes into the array inside of a foreach loop's body if you like.
When finished populating the two arrrays, use fputcsv() to properly write to your csv file.
$csv = '/home/ankur/Desktop/iq_data.csv';
$fp = fopen($csv, 'w');
$header = ['Timestamp'];
$answers = [time()];
foreach ($qna as ['question' => $header[], 'answer' => $answers[]);
fputcsv($fp, $header);
fputcsv($fp, $answers);
fclose($fp);

Related

adding array into csv file - two array values on the same row different column

I have a php page that is creating a csv file for download which is made up of an array.
Short version of Array:
$data = array("Joe Bloggs", "jbloggs", "John Doe", "jdoe")
My array is made from output from other commands so i cant just change the layout of my array, i can make two arrays, one for names and one for usernames if that help achieve my goal.
This is what i am doing to add the array values into my csv file:
$output = fopen('php://output', 'wb');
fputcsv($output, array('Name', 'Username'));
foreach ($data as $line ) {
$val = explode(",", $line);
for ($i=0; $i<$val["count"]; $i++); {
fputcsv($output , array($val[$i]));
}
}
fclose($output);
This gives me a csv that looks like this:
Name | Username
Joe Bloggs|
jbloggs |
John Does |
jdoe |
Really i need to have the usernames on the same row but in the username column.
I have tried this and lots of variations on this but it does not seem to work, my thinking was i increase N by two each time so $i will be the name because it is every other index position and then when doing the fputcsv it would add 1 to $i so it would grab the username as it is the value after the name.
foreach ($data as $line ) {
$val = explode(",", $line);
for ($i=0; $i<$val["count"]; $i+=2); {
fputcsv($output , array($val[$i], $val[$i+1]));
}
}
fclose($output);
Using the above gives me all the values in column one still.
Apologies for the write my code style question but i am out of my depth on this and cant find how to get to two consecutive values in a for loop of an array.
Here is 1 way of doing it.
$output = fopen('php://output', 'wb');
fputcsv($output, array('Name', 'Username'));
$temp = []; //Define a temp array.
foreach ($data as $line ) {
$temp[]= $line;
if( count( $temp) == 2 ) { //If no. of values in temp array is 2, write to csv file
fputcsv($output , $temp );
$temp = []; //initialize $temp;
}
}
fclose($output);
You can use simply these two line codes.
for ($i=0 ;$i < count($data);$i+2) {
fputcsv($output , $data[$i],$data[$i+1]);
}

How to force the pointer to the next row of the same column in a csv file using php?

I'm trying to write some data to the csv file and downloading it when the php file is run. I wanted to write an array in csv, and that array itself contains another array. I want to write it in the next row of the csv. I have done the following code.
<?php
header('Content-type: application/utf-8');
header('Content-disposition: attachment; filename="testexport.csv"');
$fp = fopen('php://output', 'w');
$i = 1;
$lines = array(1,2);
$columns = array();
$alphabets = array(array('a','b','b'),array('c','d','c'),array('d','e','d'));
//this array may contain any number of array, for simplicity I have defined here
foreach ($lines as $line) {
$columns['first'] = '1';
$columns['second'] = '2';
$columns['third'] = '3';
foreach ($alphabets as $alphabet) {
$columns['fourth'] = $alphabet[0];
$columns['fifth'] = $alphabet[1];
}
$columns['sixth'] = '6';
$columns['seventh'] = '7';
if($i == 1) fputcsv($fp, array_keys($columns));
fputcsv($fp, $columns);
$i++;
}
fclose($fp);
?>
My downloaded csv file currently looks like this
first second third fourth fifth sixth seventh
1 2 3 d e 6 7
1 2 3 d e 6 7
But I want the output like this.
first second third fourth fifth sixth seventh
1 2 3 a b 6 7
c d
d e
1 2 3 a b 6 7
c d
d e
I'm able understand that I'm certainly doing wrong, But I don't know how to solve it.
Can anyone help here?
Firstly, this loop is just over-writing the same variables multiple times; you are not doing anything with $colums [sic] on each loop, so no extra rows are being written to the file.
foreach ($alphabets as $alphabet) {
$colums['fourth'] = $alphabet[0];
$colums['fifth'] = $alphabet[1];
}
Secondly, fputcsv does not take any account of array keys, just the position of data in the array. So in order to align data to a particular column, you must specify empty values for the columns leading up to that.
So, you need to rearrange your loops so that you're writing a whole row for every alphabet, but leaving blanks on everything except the first. Perhaps something like this:
// Add header:
fputcsv($fp, array(
'first',
'second',
'third',
'fourth',
'fifth',
'sixth',
'seventh'
));
foreach ($lines as $line) {
$first_alphabet = true;
foreach ($alphabets as $alphabet) {
if ( $first_alphabet ) {
// Full line
fputcsv($fp, array(
'1',
'2',
'3',
$alphabet[0],
$alphabet[1],
'6',
'7'
));
$first_alphabet = false;
} else {
// Partial line
fputcsv($fp, array(
'',
'',
'',
$alphabet[0],
$alphabet[1],
'',
''
));
}
}
}

How can I pull 2 paired elements from a csv file and add them to an array using PHP?

I have several csv files that contain order information for products. My csv files look something like below:
order_number,sku,qty,price_per,total_price
12345,55555,25,4,100
12346,33333,10,5,50
12347,55555,20,4,80
I'm not having any trouble finding out the total_price for all transactions, but how can I find the totals on each product? I tried creating an array for each, but I can't figure out how to keep the sku and total_price elements bound together.
Update #2
Since I can't have an array with matching keys, and since I want to end up here anyway, how can I get an array like this:
Array(
[55555] => 180
[33333] => 50
)
If anyone has any ideas on how I can make this array that would be great. Thanks!
Update #1
Sorry, I spaced adding my code, here it is:
foreach($files as $file){
$fh = fopen($file, 'rb');
while($col = fgetcsv($fh)) {
$csv[] = $col;
$total = array($col[27])
}}
This will do what you want, i.e. create an array $totals which sums the totals over skus:
$totals = array();
foreach($files as $file) {
$fh = fopen($file, 'rb');
while($col = fgetcsv($fh)) {
$csv[] = $col;
$total = array($col[27])
$totals[$col[1]] += $col[27];
}
}
Current answers don't produce the array you're after:
Array(
[55555] => 100
[33333] => 50
[55555] => 80
)
Because this can't be done - 55555 can't be used as a key twice. An alternative would be to have an array of the form:
Array(
[12345] => array("sku"=>55555,"total_price"=>100),
[12346] => array("sku"=>33333,"total_price"=>50),
[12347] => array("sku"=>55555,"total_price"=>80),
)
This code produces the second array:
$trans = array();
foreach($files as $file){
$fh = fopen($file, 'rb');
while($col = fgetcsv($fh)) {
$trans[$col[0]] = array("sku"=>$col[0],"total_price"=>$col[27]);
}
}
Assuming $col[0] is order and $col[1] is sku.

Php and javascript array - skipping blank values and adding to new array?

I have an array in php that contains all the lines of a text files (each line being one value of the array). My text file had blank lines so the array has blank lines too. I wanted to search the array for a certain value like this:
$array = array();
$lines = file("textfile.txt"); //file in to an array
foreach ($lines as $line)
{
if (stripos($line, "$$") !== false)
{
$array[] = str_replace("$$", "", $line);
}
}
The code above is searching for a $$ and replacing it with a blank. The text file holds a line with a $$1 or any number and I want it to find all instances of that line, which it is doing.
My problem is that I want it to find the next 5 lines that aren't blank after finding the $$(number) and put them into a multi dimensional array. The multidimensional array looking similar to this (the program is a test in case you are wondering why the array is named the way it is):
$test = array(
array('question' => 'What is the answer', 'ansa' => "answera", 'ansb' => "answerb", 'ansc' => "answerc", 'ansd' => "answerd"), // $test[1]
array('question' => 'What is the answer', 'ansa' => "answera", 'ansb' => "answerb", 'ansc' => "answerc", 'ansd' => "answerd"), // $test[2]
);
The next five lines after the $$(number) are a question and four answers that need to go into the array. My code with regxp and searching isn't working so i discarded it.
you can try something like this...
<?php
$lines = array_filter(file('text.txt')); //file in to an array
$questions = array();
// find your starts and pull out questions
foreach ($lines as $k=>$line)
{
if (stripos($line, "$$") !== false)
{
$questions[] = array_slice($lines, $k, 5);
}
}
// dump
var_dump($questions);
See php manual for array_slice
Have you looked at preg_replace_callback?
Something along these lines should work:
<?php
function replace_callback($matches) {
var_dump($matches);
}
preg_replace_callback('/\$\$[0-9]+\s+([^'.PHP_EOL.']+){5}/is', 'replace_callback', file_get_contents('textfile.txt'));
?>

problem with PHP reading CSV files

I'm trying to read data from a.csv file to ouput it on a webpage as text.
It's the first time I'm doing this and I've run into a nasty little problem.
My .csv file(which gets openened by Excel by default), has multiple rows and I read the entire thing as one long string.
like this:
$contents = file_get_contents("files/data.csv");
In this example file I made, there are 2 lines.
Paul Blueberryroad
85 us Flashlight,Bag November 20,
2008, 4:39 pm
Hellen Blueberryroad
85 us lens13mm,Flashlight,Bag,ExtraBatteries November
20, 2008, 16:41:32
But the string read by PHP is this:
Paul;Blueberryroad 85;us;Flashlight,Bag;November 20, 2008, 4:39 pmHellen;Blueberryroad 85;us;lens13mm,Flashlight,Bag,ExtraBatteries;November 20, 2008, 16:41:32
I'm splitting this with:
list($name[], $street[], $country[], $accessories[], $orderdate[]) = split(";",$contents);
What I want is for $name[] to contain "Paul" and "Hellen" as its contents. And the other arrays to receive the values of their respective columns.
Instead I get only Paul and the content of $orderdate[] is
November 20, 2008, 4:39 pmHellen
So all the rows are concatenated. Can someone show me how i can achieve what I need?
EDIT: solution found, just one werid thing remaining:
I've solved it now by using this piece of code:
$fo = fopen("files/users.csv", "rb+");
while(!feof($fo)) {
$contents[] = fgetcsv($fo,0,';');
}
fclose($fo);
For some reason, allthough my CSV file only has 2 rows, it returns 2 arrays and 1 boolean. The first 2 are my data arrays and the boolean is 0.
You are better off using fgetcsv() which is aware of CSV file structure and has designated options for handling CSV files. Alternatively, you can use str_getcsv() on the contents of the file instead.
The file() function reads a file in an array, every line is an entry of the array.
So you can do something like:
$rows = array();
$name = array();
$street = array();
$country = array();
$rows = file("file.csv");
foreach($rows as $r) {
$data = explode(";", $r);
$name[] = $data[0];
$street[] = $data[1];
$country[] = $data[2];
}
I've solved it now by using this piece of code:
$fo = fopen("files/users.csv", "rb+");
while(!feof($fo)) {
$contents[] = fgetcsv($fo,0,';');
}
fclose($fo);
For some reason, allthough my CSV file only has 2 rows, it returns 2 arrays and 1 boolean. The first 2 are my data arrays and the boolean is 0.
The remark about fgetcsv is correct.
I will still answer your question, for educational purpose. First thing, I don't understand the difference between your data (with comas) and the "string read by PHP" (it substitutes some spaces with semi-colon, but not all?).
PS.: I looked at the source code of your message, it looks like an odd mix of TSV (tabs) and CSV (coma).
Beside, if you want to go this way, you need to split first the file in lines, then the lines in fields.
The best way is of course fgetcsv() as pointed out.
$f = fopen ('test.csv', 'r');
while (false !== $data = fgetcsv($f, 0, ';'))
$arr[] = $data;
fclose($f);
But if you have the contents in a variable and want to split it, and str_getcsv is unavailable you can use this:
function str_split_csv($text, $seperator = ';') {
$regex = '#' . preg_quote($seperator) . '|\v#';
preg_match('|^.*$|m', $text, $firstline);
$chunks = substr_count($firstline[0], $seperator) + 1;
$split = array_chunk(preg_split($regex, $text), $chunks);
$c = count($split) - 1;
if (isset($split[$c]) && ((count($split[$c]) < $chunks) || (($chunks == 1) && ($split[$c][0] == ''))))
unset($split[$c]);
return $split;
}

Categories