Create key-value pair from csv php - php

I have a csv file like below
tl_blade_thickness,tl_blade
test1,test1
test2,test2
test3,test3
test4,test4
test5,test5
test6,test6
test7,test7
test8,test8
test9,test9
I'm trying to create a key value pair array like below.
["tl_blade_thickness"=>["test1","test2","test3",...],tl_blade=>["test1","test2","test3",...]]
I tried like this below.
$content = fopen("csv.csv", "r");
$all_rows = array();
$header = fgetcsv($content);
while ($row = fgetcsv($content)) {
$all_rows[] = array_combine($header, $row);
}

Use the first line of the file to create the keys of the array. Then push each field of the remaining lines into the corresponding element keys.
$content = fopen("csv.csv", "r");
$headers = fgetcsv($content);
$all_rows = array_fill_keys($headers, []);
while ($row = fgetcsv($content)) {
foreach ($headers as $i => $name) {
$all_rows[$name][] = $row[$i];
}
}

Related

How to sort a CSV file by a column and then sort by a second column, then saving the CSV file

I'm looking to read a CSV export file with PHP. I have access to the File Path Variable called $file_path.
How would I sort the CSV export file by a specific column and then sort it again by a second column? and then save the CSV file to the same file name and file path.
UPDATE:
I got it to read the CSV, then sort it and also save it to the CSV. However, it's also sorting the headers. I am trying to use array_shift and array_unshift but when I use array_shift with a multi-layer array, I am getting an error. (unshift works fine though).
function wp_all_export_after_export($export_id, $exportObj)
{
// Check whether "Secure Mode" is enabled in All Export -> Settings
$is_secure_export = PMXE_Plugin::getInstance()->getOption('secure');
if (!$is_secure_export) {
$filepath = get_attached_file($exportObj->attch_id);
} else {
$filepath = wp_all_export_get_absolute_path($exportObj->options['filepath']);
}
$handle = fopen($filepath, 'r') or die('cannot read file');
$binNumber = array();
$category = array();
$rows = array();
$header = array();
//build array of binNumbers, Categories, and array of rows
while (false != ( $row = fgetcsv($handle, 0, ',') )) {
$binNumber[] = $row[3];
$category[] = $row[1];
$rows[] = $row;
}
fclose($handle);
$header = $rows[0];
array_shift($rows);
//sort array of rows by BinNumber & then Category using our arrays
array_multisort($binNumber,SORT_ASC, $category, SORT_ASC, $rows);
array_unshift($rows,$header);
$file = fopen($filepath,"w");
foreach ($rows as $line) {
fputcsv($file, $line);
}
fclose($file);
}
add_action('pmxe_after_export', 'wp_all_export_after_export', 10, 2);

How to pull csv import into an associative array and name the keys automatically?

I have a csv file where the first line shows the name of each row. This name should be the key for an associative array. Currently I am pulling this in manually and if the row order changes it will break the functionality.
How can I retrieve the names from line 1 and create keys out of it?
$csv = array();
$index = 0;
while ($row = fgetcsv($fp)) {
if ($row[0] == NULL)
continue;
else{
$index++;
foreach($row as $csvdata){
list(
$csv[$index]['column 1 name'],
$csv[$index]['column 2 name']
)
= explode(';',$csvdata);
}
}
}
Try converting the very first line of the file, which contains the names/keys, into an array. Then use those keys to populate the associate array as you parse the remaining lines.
$keys = array();
$csv = array();
$index = 0;
while ($row = fgetcsv($fp)) {
if ($index == 0) {
$keys = explode(',', $row);
}
else {
$csv[$keys[index-1]] = $row;
}
++$index;
}
This answer assumes that what you want here is an associate array where the keys correspond to the names in the first row, and the values correspond to each row in the CSV import.

CSV data to array_map and str_getcsv using delimiter

My problem is I'm unable to pass 2nd parameter to str_getcsv function.
$rows = array_map('str_getcsv', file($filePath_product_names_t), [";"]);
$header = array_shift($rows);
$csv = [];
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
CSV structure
"25";"some text"; "also some Text"
And also getting WARNING:
array_combine(): Both parameters should have an equal number of
elements
Try this:
$rows = array_map(function($v){return str_getcsv($v, ";");}, file($filePath_product_names_t));
$header = array_shift($rows);
$csv = [];
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
print_r($rows);
Combining the two problems, the first is that you can't pass a parameter the way you are trying in the array_map() so as in the link I posted in the comments, you can create an anonymous function to do this.
The second is that, in some cases a CSV file doesn't always have all the data for a row in the file. In this case the header row and the other rows don't have the same amount of data, so use array_pad() to add blanks to make sure they do have the same length. To combine these into the code...
$rows = array_map(function($data) { return str_getcsv($data,";");}
, file($filePath_product_names_t));
$header = array_shift($rows);
$csv = [];
foreach($rows as $row) {
$row = array_pad($row, count($header), "");
$csv[] = array_combine($header, $row);
}
print_r($csv);

Checking while loop key exists in seperate array

Having checked a variety of questions but not being able to find quite what I need, I am at a bit of a loss.
I am trying to chose the columns from MySQL I want exported to CSV by parsing the column names and adding the valid column names to a $colnames array, then adding those values as headers to the CSV and then only displaying the relevant data from the database through a while loop.
I have looked at the following in particular having been guided there from other questions: How to get all the key in multi-dimensional array in php
Here is the code:
function query_to_csv($query, $filename, $attachment = false, $headers = true, $specs_off = false) {
if($attachment) {
// send response headers to the browser
header( 'Content-Type: text/csv; charset=UTF-8' );
header( 'Content-Disposition: attachment;filename='.$filename);
$fp = fopen('php://output', 'w');
} else {
$fp = fopen($filename, 'w');
}
$result = mysql_query($query) or die( mysql_error() );
if($headers) {
// output header row (if at least one row exists)
$row = mysql_fetch_assoc($result);
if($row) {
// PRODUCTS TABLE SPECIFIC - get rid of specs_ and free_ columns so have nicer data set for user
if($specs_off) {
$columnames = array_keys($row);
$colnames = array();
//$colnames = array_keys($row);
foreach($columnames as $key => $value) {
if((substr_count($value, "spec_") < 1) && (substr_count($value, "free_") < 1)) {
array_push($colnames, $value);
}
}
}
else {
$colnames = array_keys($row);
}
// add in additional columns if exporting client data
if($table == 'clients') {array_push($colnames, "products", "last_order_date");}
//write the colnames to the csv file
fputcsv($fp, $colnames);
// reset pointer back to beginning
mysql_data_seek($result, 0);
}
} // done with the headers etc, now lets get on with the data
// clear out and create the $row_data array
$row_data = array();
// run through the row array adding values to row_data as we go
while($row = mysql_fetch_assoc($result)) {
// create the array_keys_multi from https://stackoverflow.com/questions/11234852/how-to-get-all-the-key-in-multi-dimensional-array-in-php/11234924#11234924
function array_keys_multi(array $array) {
$keys = array();
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($array[$key])) {
$keys = array_merge($keys, array_keys_multi($array[$key]));
}
}
return $keys;
}
// run the function on the $row array
array_keys_multi($row);
// now use the $keys array
foreach($keys as $key => $value) {
// check if the value is in the colnames array and if so push the data on to the $row_data array ready for export to CSV
if(in_array($value, $colnames)) {
array_push($row_data, $row[$value]);
}
}
// now we are ready to write the CSV
fputcsv($fp, $row_data);
}
fclose($fp);
exit;
} // end of query_to_csv
// Write the sql statement
$sql = "SELECT * FROM ".$table." ";
if(isset($where_1_col)) { $sql .= " WHERE `".$where_1_col."` = '".$where_1_val."'"; }
if(isset($where_2_col)) { $sql .= " AND `".$where_2_col."` = '".$where_2_val."'"; }
if(isset($where_3_col)) { $sql .= " AND `".$where_3_col."` = '".$where_3_val."'"; }
if(isset($where_4_col)) { $sql .= " AND `".$where_4_col."` = '".$where_4_val."'"; }
if(isset($order_by_col)) { $sql .= " ORDER BY `".$order_by_col."` ". strtoupper($order_by_dir) ." "; }
// output as an attachment
query_to_csv($sql, $table."_export.csv", true, true, true);
All I am getting is a huge export of the chosen column names repeated as many times as there are values from the initial query. I don't know how to get the values in.
Any suggestions on where I am going wrong or how I can undertake this more neatly are welcomed.
It seems that you just append the new row data to $row_data but never clear that array.
array_push($row_data, $row[$value]);
What I did to fix it:
Move
// clear out and create the $row_data array
$row_data = array();
into the while loop.
Change
// clear out and create the $row_data array
$row_data = array();
while($row = mysql_fetch_assoc($result)) {
...
}
To
while($row = mysql_fetch_assoc($result)) {
// clear out and create the $row_data array
$row_data = array();
...
}
Note:
You are using $table everywhere but never define it. Like here if($table == 'clients')
If it is a global var you need to add global $table or a parameter to your function, too.
Edit:
As mentioned in my comment on your question you could just use array_keys() to get the keys.
php.net/manual/de/function.array-keys.php
And then change
array_keys_multi($row);
to
$keys = array_keys($row);
After that you can remove array_keys_multi()
Further you could move that part in front of your while-loop because you only need to calculate the column names you need once and not in every iteration.

PHP read in specific csv file column as an array

I am new to PHP and would like to be able to read in a csv file which has two columns, one is the number (kind of like a ID) then the other holds a integer value. I have looked up the fgetcsv function but I have not been able to find a way to read a specific column from the csv file.
I would like to get all the values from the second column only, without the heading.
Any way of doing this?
This is what I have so far:
$file = fopen('data.csv', 'r');
$line = fgetcsv($file);
And this is some sample data from the csv file:
ID,Value
1,243.00
2,243.00
3,243.00
4,243.00
5,123.11
6,243.00
7,180.00
8,55.00
9,243.00
Any help would be appreciated.
Thanks.
fgetcsv() only reads a single line of the file at a time. You'll have to read the file in a loop to get it all:
$data = array();
while($row = fgetcsv($file)) {
$data[] = $row;
}
The heading you can skip by doing an fgetcsv once outside the loop, to read/trash the header values. And if you only want the second column, you can do:
$data[] = $row[1];
However, since you've got data in there, maybe it might be useful to keep it, plus key your new array with the ID values in the csv, so you could also have:
$data[$row[0]] = $row[1];
and then your nice shiny new array will pretty much exactly match what's in the csv, but as an array keyed by the ID field.
$csv = array_map("str_getcsv", file("data.csv", "r"));
$header = array_shift($csv);
// Seperate the header from data
$col = array_search("Value", $header);
foreach ($csv as $row) {
$array[] = $row[$col];
}
// Iterate through data set, creating array from Value column
$header = fgetcsv($h);
$rows = array();
while ($row = fgetcsv($h)) {
$rows []= array_combine($header, $row);
}
$fp = fopen($filePath, "r+");
$header = fgetcsv($fp);
while ($members = fgetcsv($fp)) {
$i = 0;
foreach ($members as $mem) {
$membersArray[ $i ][ ] = $mem;
$i++;
}
}
$newArray = array_combine($header, array_map("array_filter",$membersArray));
You can also use this class http://code.google.com/p/php-csv-parser/
<?php
require_once 'File/CSV/DataSource.php';
$csv = new File_CSV_DataSource;
$csv->load('data.csv');
var_export($csv->connect());
?>

Categories