I am trying to import a CSV for a shop, with a subset of data from an existing CSV file. I need to split one item from a column (column 3, category_id) that contains multiple comma-separated values, then combine it with one other column (Product_id) to produce multiple rows in the import CSV. See the following examples.
Original CSV
Product_id;article_id;category_id;
"1";"0001";"2,4,6"
Need it into a new CSV file
Product_id;category_id
"1";"2"
"1","4"
"1","6"
I tried just the fegetcsv function to read in the CSV and to printout the whole into an array but I have no idea what to do next.
<?php
$handle = fopen ("articles.csv","r");
while ( ($data = fgetcsv ($handle, 1000, ";")) !== FALSE ) {
$column3[] = $data[3];
}
fclose ($handle);
//edit:
print_r($column3);
?>
I get:
Array ([0] => category_id [1] => 1 [2] => 0001 [3] => 2,4,6
Quick and dirty:
$csvData = file('articles.csv');
$matches = array();
$output = "";
foreach($csvData as $csvLine) {
if(preg_match('/"(.+)";".+";"(.+)"/', $csvLine, $matches))
{
$numbers = explode(',', $matches[2]);
foreach($numbers as $number) {
$output .= "\"{$matches[1]}\";\"{$number}\"" . PHP_EOL;
}
}
}
Related
This question already has answers here:
How to count non-empty entries in a PHP array?
(5 answers)
Closed last year.
I have one CSV file. It contains 3 columns I want to count only the 3rd column total rows. I tried with one code but It showed the whole CSV file rows counts.
$record = file('filename.csv', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$total_record = count($record);
echo $total_record; // output 6
As per the below image, I want to count only the Ph_no column. Please help me out
You could use array_map() to run callback str_getcsv() on each element (row) in the array that is returned by file().
$arr = array_map('str_getcsv', file('./filename.csv'));
The result ($arr) would look something like this:
Array
(
[0] => Array
(
[0] => First_Name
[1] => Last_name
[2] => Ph_no
)
[1] => Array
(
[0] => ABC
[1] => AB
[2] => 1234567890
)
... etc.
You can then count the number of phone numbers:
$phNo = array_column($arr, 2);
$phNoCount = count($phNo) -1 ; // subtract the header
echo 'Ph_no count: ' . $phNoCount;
$file = fopen('myCSVFile.csv', 'r');
$count = 0;
while (($line = fgetcsv($file)) !== FALSE) {
$num = count($line);
for ($i=0; $i < $num; $i++) {
if(!empty($line[2]) {
$count++;
}
}
}
fclose($file);
echo $count;
Using the fgetcsv() function it is quite simple
$tot = 0;
if (($f = fopen("filename.csv", "r")) !== FALSE) {
// read and ignore first line, titles
fgetcsv($f, 1000, ",");
while (($line = fgetcsv($f, 1000, ",")) !== FALSE) {
if ( $line[2] !== '' ) {
$tot += $line[2]; // accumulate column 3
}
}
}
fclose($f);
echo $tot;
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]);
}
I want to build an array to create a CSV file using variables. The $arraybuild variable will gather lines from a search so will never be the same amount of rows.
$arraybuild = "'aaa,bbb,ccc,dddd',";
$arraybuild .= "'123,456,789',";
$arraybuild .= "'\"aaa\",\"bbb\"'";
$list = array
(
$arraybuild
)
;
$file = fopen("contacts.csv","w");
foreach ($list as $line)
{
fputcsv($file,explode(',',$line));
}
fclose($file);
The problem is the result does not separate the lines, it places them all in the same line.
I want to get
aaa,bbb,ccc,dddd
123,456,789
"aaa","bbb"
What I am getting is
aaa bbb ccc dddd 123 456 789 "aaa" "bbb"
All in separate columns
Can someone please assist?
Push each rows to an array instead of concatenating to a string, then loop and add to csv
$arraybuild[] = "'aaa,bbb,ccc,dddd',";
$arraybuild[] = "'123,456,789',";
$arraybuild[] = "'\"aaa\",\"bbb\"'";
$file = fopen("contacts.csv","w");
foreach ($arraybuild as $line) {
fputcsv($file, explode(',', $line));
}
fclose($file);
In your code, you are concatenating all values to one string, separated by ,. After that, you are creating one array with one element in it (that long string).
So, it's not a surprise, that you are getting all of them on the same line.
To separate lines, you should create separate arrays inside the $list array. Each included array will be on the new line.
Try this:
<?php
$arraybuild1 = "'aaa,bbb,ccc,dddd',";
$arraybuild2 = "'123,456,789',";
$arraybuild3 = "'\"aaa\",\"bbb\"'";
$list = array
(
explode(',', $arraybuild1),
explode(',', $arraybuild2),
explode(',', $arraybuild3)
);
$file = fopen("contacts.csv", "w");
foreach ($list as $fields) {
fputcsv($file, $fields);
}
fclose($file);
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.
Below script is shown search string in a text file, my text file has contents like:
60, 1, 1, 188, pdgje5566
60, 1, 1, 188, pdgje5565
if(!empty($extTxId)){
$searchfor = $extTxId;
$matches = array();
$handle = #fopen($file, "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
if(strpos($buffer, $searchfor) !== FALSE)
$matches[] = $buffer;
}
fclose($handle);
}
print_r($matches);
it output as
Array ( [0] => 60, 1, 1, 188, ppje5566 )
however i want to explode the data which is separate by comma(,) and store into variable, is that anyway to do it?
thanks.
i want to explode the data which is separate by comma(,)
Use explode().
If this is a CSV file (or some other delimited file), I suggest looking at fgetcsv(). It is effectively fgets() and explode(), which seems to be what you need.
Since you have spaces between each comma, you can trim each element.
// Iterate through each item int the array (you can do $matches[0] if you just want the first)
foreach ($matches as $match)
{
$output_array = array_map('trim',explode(',',$match));
print_r($output_array);
}
Output:
Array
(
[0] => 60
[1] => 1
[2] => 1
[3] => 188
[4] => pdgje5565
)
Example: http://codepad.org/aSyVX5Bj
Try like
foreach(Array[0] as $element)
{
echo $element;
}
If you know the exact structure of the input you're getting, you could do something like:
$string = '60, 1, 1, 188, pdgje5565';
// Using trim just to be sure
list($varA, $varB, $varC, $varD, $varE) = explode(', ', trim($string));
This way you would get the results as follows:
$varA = 60;
$varB = 1;
$varC = 1;
$varD = 188;
$varE = 'pdgje5565';
The main advantage here is you would get decent variables instead of array with abstract indexes, but it is only good if you're sure about you're structure being constant.