I have a php code that takes the matched rows of a csv file and puts them in an array.
my csv file looks like this:
Company,Produkt,Sortiment name,31,32,33,34,35,36,37,38 //these are shoe sizes
Dockers,AD1234,Sort A,2,3,5,3,2,1,0,0 //and these numbers are how many pairs of shoes
Addidas,AB1234,Sort B,2,2,1,4,,0,0,4,3
Nike,AC1234,Sort C,0,2,0,1,4,0,4,3
Dockers,AE1234,Sort D,0,1,2,3,4,1,0,2
and my php code is
$csv = file_get_contents($_SERVER['DOCUMENT_ROOT'] . 'CsvTest/Sortiment.csv');
$input = 'Company'; // column
$value = 'Dockers'; // what value of that column
$csv = array_map("str_getcsv", explode(PHP_EOL, $csv));
$keys = array_shift($csv);
$key = array_search($input, $keys);
$sortiment_array = array();
while ($line = array_shift($csv)) {
if ($line[$key] == $value) {
$line = implode(',', $line) . PHP_EOL;
$sortiment_array[] = $line;
}
}
so var_dump($sortiment_array); will give me the following
array(2) {
[0]=>
string(39) "Dockers,AD1234,Sort A,2,3,5,3,2,1,0,0"
[1]=>
string(39) "Dockers,AE1234,Sort D,0,1,2,3,4,1,0,2"
}
What I would like to do is to have the 0 columns taken out from the array and so therefore I need to identify what pair of shoes was not 0 ? So I need the first row (which is the header for my case) to repeat itself for each key and take out the shoe size that had 0 pairs. basically my array should turn into something like:
array(2) {
[0]=>array(2)
['shoe size']=> "Producer,Produkt,Sortiment name,31,32,33,34,35,36" // no 37,38
['sortiment']=> "Dockers,AD1234,Sort A,2,3,5,3,2,1,"// no 0
[1]=>array(2)
['shoe size']=> "Producer,Produkt,Sortiment name,32,33,34,35,36,38" // no 31, 37
['sortiment']=> "Dockers,AE1234,Sort D,1,2,3,4,1,2"
}
Basically in 'shoe size' sizes should be taken out where the matched row has 0 pairs for that size. I hope I can explain it. I tried my best. Any suggestions?
If all the rows in the data are the same size, you can combine the keys and values for each line that matches, then filter that to remove the zeros.
while ($line = array_shift($csv)) {
if ($line[$key] == $value) {
// combine keys and values, and filter to remove zeros
$filtered = array_filter(array_combine($keys, $line));
// separate the resulting keys and values and add them to your output array
$sortiment_array[] = [
'shoe size' => implode(',', array_keys($filtered)),
'sortiment' => implode(',', $filtered)
];
}
}
<?php
$csv = file_get_contents($_SERVER['DOCUMENT_ROOT'] . 'CsvTest/Sortiment.csv');
$input = 'Company'; // column
$value = 'Dockers'; // what value of that column
$csv = array_map("str_getcsv", explode(PHP_EOL, $csv));
$keys = array_shift($csv);
$key = array_search($input, $keys);
$sortiment_array = array();
while ($line = array_shift($csv)) {
if ($line[$key] == $value) {
$lineStr = implode(',', $line) . PHP_EOL;
$outputKeys = [];
$outputLine = [];
// Look through $line to find non-'0' elements and for each of them,
// add the corresponding elements to $outputKeys and $outputLine:
for( $i=0; $i < sizeof($keys); $i++ ) {
if ( $line[$i] !== '0' ) { // No '0' in this slot so add this slot to $outputKeys and $outputLine:
$outputKeys[] = $keys[$i];
$outputLine[] = $line[$i];
}
}
// Join $outputKeys and $outputLines back into a string:
$sortiment_array[] = [
join(',', $outputKeys),
join(',', $outputLine)
];
}
}
print_r($sortiment_array);
You can implement the logic which does it for a pair of arrays, the first being the template (header row) and the second the csv row after the header.
function nonZeros($template, $row) {
$output = [
'shoe_size' => [],
'sortiment' => []
];
for ($index = 0; $index < count($row); $index++) {
if ($row != 0) {
$output['shoe_size'][]=$template[$index];
$output['sortiment'][]=$row[$index]
}
}
return $output;
}
and then you can loop the lines and call nonZeros, passing the corresponding arrays.
I have csv file with 1500+ entries in a column.I can able to read csv file's all values of column with this.
$rowcount = 1;
$srcFileName = "input/test.csv";
$file = fopen($srcFileName,"r");
$inputfielscount = count(file($srcFileName, FILE_SKIP_EMPTY_LINES));
while($rowcount < $inputfielscount)
{
$row = fgetcsv($file);
$result=array("id" =>$row[0],"des"=>"I am jhon",salery="10000");
$Final=array("listingsEmp"=>$result);
}
After reading first (1-10) value i will create an array (like array [0] =>$result) and Then wantto repeat same task from (11-20) and create another array (like array [1] =>$Final this time $final array contain information about the next ids whic we read from csv file (11-10)) and so on.
For the above requirment i changed code to this :
$rowcount = 1;
$srcFileName = "input/test.csv";
$file = fopen($srcFileName,"r");
while($rowcount < 20)
{
if(($rowcount % 10 == 0) && ( $rowcount != 0)) {
$rowcount++;
break;
}else{
$row = fgetcsv($file);
// some curl code for fetching data according to csv file field(Id)
$result=array("id" =>$row[0],"des"=>"I am jhon",salery="10000"); //contain 10 array
}
}
$Final=array("listingsEmp"=>$result);
Now i will post this $final array which has (0-10 index array ,each has unique id and corresponding values) using curl and get response which i am save in csv file.
$currenttime=date("Y-m-d-H_i_s");
$opfile='output'.$currenttime.'.csv'; //path wher op csv file exist
if(!#copy($srcFileName,'/output/'.$opfile))
{
$errors= error_get_last();
echo "COPY ERROR: ".$errors['type'];
echo "<br />\n".$errors['message'];
}else { // echo "File copied from remote!";
$fp = fopen('output/output'.$currenttime.'.csv',"a");
$fr = fopen($srcFileName,"r");
$rowcounts=0;
$FinalRES=$Final->response;
while($rowcounts< $inputfielscount) {
$resultBulk=$FinalRES[$rowcounts];
$resultBulkStatus=$FinalRES->status;
$resultBulkErrors=$FinalRES->errors;
$errorMsgArray=$resultBulkErrors[0];
$BulkErrorsMessage=$errorMsgArray->message;
$rows = fgetcsv($fr);
if($resultBulkStatus=='failure'){
$list = array ($rows[0],$rows[1],$resultBulkStatus,$BulkErrorsMessage);
}else {
$list = array ($rows[0],$rows[1],$resultBulkStatus,"successfully");
}
fputcsv($fp,$list);
//$p++;
$rowcounts++;
}
}
This full code runs once and give response for 10 ids ,i want repeat this code again for next 10 id (11-20)and then for (21-30) so on .
Once all response write in output csv file After that it display download output file link,Output file contain full response for all Ids which is in csv file(1500 +)
<?php $dnldfilw='output'.$currenttime.'.csv';?>
<a href='download.php?filename=<?php echo $dnldfilw; ?>'>Download Output file</a>
?>
The easiest method is to just use the file() function you are already using...
So to shorten the code to some pseudocode:
<?php
$indexedArray = array();
$indexedSplit = 10;
$lines = file($srcFileName);
$tempArray = array();
foreach($lines as $line) {
if(count($tempArray) % $indexedSplit === 0) {
$indexedArray[] = $tempArray;
$tempArray = array();
}
$tempArray[] = $line;
}
foreach($indexedArray as $index => $valueArray) {
// do the curl magic
// write results of curl into csv
}
Your question is poorly phrased, but I think this would be your aim, right?
I have made this PHP script that should take an array and for each element in the array - generate a csv file. Unfortunately something is wrong. It doesn't store any of the files in the directory specified. But it doesn't return any errors neither. Maybe someone can see the problem?
$ids = json_decode($_POST['jsonarray']); // array sent with ajax
$start = $_POST['start']; // date sent with ajax
$end = $_POST['end']; // date sent with ajax
$start_date = date('yyyy-mm-dd', strtotime($start)); // format dates to sql firendly
$end_date = date('yyyy-mm-dd', strtotime($end));
$toZip = array(); // Prepare array to files for zip
if(is_array($ids)) {
foreach ($ids as $key => $qr)
{
// Get labels first
// Here we prepare the first line in the .CSV file
$tb = $qr . '_labels';
$sql = $user_pdo->query("SELECT * FROM $tb");
$head_array = array('Log ID', 'Timestamp');
while ($row = $sql->fetch(PDO::FETCH_ASSOC))
{
// This array is the first line in the .CSV file
$head_array[] = $row['label'];
}
// Get ready for looping through the database
$table = $qr . '_data';
$results = $user_pdo->prepare("SELECT * FROM $table WHERE timestamp BETWEEN :start_date AND :end_date;");
$results->bindParam(':start_date', $start_date, PDO::PARAM_STR);
$results->bindParam(':end_date', $$end_date, PDO::PARAM_STR);
$results->execute();
// Pick a filename and destination directory for the file
$filename = "temp/db_user_export_".time().".csv";
// Actually create the file
// The w+ parameter will wipe out and overwrite any existing file with the same name
$handle = fopen($filename, 'w+');
// Write the spreadsheet column titles / labels
fputcsv($handle, $head_array);
// Write all the user records to the spreadsheet
foreach($results as $row)
{
// amount of rows is unknown
$rows = $row->rowCount();
$insert_array = array();
for ($i=0; $i<=$rows; $i++)
{
// function goes here
$insert_array[] = $row[$i];
}
fputcsv($handle, $insert_array);
}
// Finish writing the file
fclose($handle);
$toZip[] = $filename;
}
}
Example on var_dump($ids);
array(4) {
[0]=>
string(5) "t23ry"
[1]=>
string(5) "6us32"
[2]=>
string(5) "se43z"
[3]=>
string(5) "o00gq"
}
I found the answer. After a long time searching and playing around, I saw that this function
foreach($results as $row)
{
// amount of rows is unknown
$rows = $row->rowCount();
$insert_array = array();
for ($i=0; $i<=$rows; $i++)
{
// function goes here
$insert_array[] = $row[$i];
}
fputcsv($handle, $insert_array);
}
didn't work because of following:
$rows = $row->rowCount(); has to be $rows = count($row);
The number of string in the returned $row array was higher than expected so I needed to change my select statement to $results = $user_pdo->query("SELECT * FROM $table WHERE timestamp >= '$start' AND timestamp <= '$end'";, PDO::FETCH_NUM);. This will only give me the rows in numeric order, which will make the $row[$i] -> array work.
Also as you can see, I changed the prepared statement to a query instead, and also changes the start date and end date variables to be unformatted.
This really took some time, but it is finally working. Thanks a lot for all the support guys.
fputcsv only outputs a line at a time. Change this:
for ($i=0; $i<=$rows; $i++)
{
// function goes here
$insert_array[] = $row[$i];
}
fputcsv($handle, $insert_array);
To this:
for ($i=0; $i<=$rows; $i++)
{
// function goes here
fputcsv($handle, $row[$i]);
}
When I ouput these txt files, I am trying to group them by unique county with a count limitation per county file. For example, let's say the query returns 2 unique counties in this accessable result field: $row['county_txt'].. Let's say I set the $per_file limitation to 2500. I have the script working now with the per_file etc but not with the counties grouping. Below is somewhat of a mash of where I am at. Thanks for any guidance in helping me resolve this.
Output examples:
Green County - Total Green county results 2900 output would be 2 files.
Output files would be:
Green-#1-20130627-2500.txt
Green-#2-20130627-400.txt
Red County - Total Red county results 12650 output would be 5 files.
Output files would be:
Red-#1-20130627-2500.txt
Red-#2-20130627-2500.txt
Red-#3-20130627-2500.txt
Red-#4-20130627-2500.txt
Red-#5-20130627-150.txt
... // earlier part of script
// Functions I've been attempting
$county[] = $row['county_txt'];
function unique_county() {
foreach($county as $unq_cnty) {
echo $unq_cnty;
return $unq_cnty;
}
}
function get_unique_county() {
$column = array();
while($row = mysql_fetch_array($result)){
$column[] = array_unique($row['county_txt']);
echo $column;
}
}
get_unique_county();
$file_count = 1;
$recs = 0;
$per_file = 2500;
$footer = "FOOTER";
$default_contents = $contents = array("BODY CONTENT TOP");
while ($row = mysql_fetch_array($result)) {
$line = "...";
$contents[] = $line; // Each array element will be a line in the text file
$i++;
$recs++;
if ($county == $unq_cnty && $i == $per_file) {
$contents[] = $footer; // Add the footer to the end
file_put_contents($unq_county . "-#" . $file_count . "-" . date('Y') . "-" . $recs . '.txt', implode("\r\n", $contents));
$i = 0;
$recs = 0;
$contents = $default_contents;
$file_count++;
} // End of if()
} // End of while()
You need a counter, and then be able to reset it (upon resetting it, you save the file).
Example (untested, example only):
<?php
$rowCounter = 0;
$fileCounter = 1;
$startID = md5(microtime(1));
$fp = fopen("{$startID}.txt", "w");
while ($row = mysql_fetch_array($result)) {
$rowCounter++;
fwrite($fp, $row['county_txt']."\r\n");
if($rowCounter == 2500) {
fclose($fp);
if($startID) {
rename("{$startID}.txt", "Red-#{$fileCounter}-".date("Ymd")."-{$rowCounter}.txt");
$startID = md5(microtime(1));
}
$fp = fopen("{$startID}.txt", "w");
$rowCounter = 0;
$fileCounter++;
}
}
// Save last file
fclose($fp);
rename("{$startID}.txt", "Red-#{$fileCounter}-".date("Ymd")."-{$rowCounter}.txt");
?>
On that note, don't use mysql_* functions. Instead, use mysqli at the very least, or PDO.
Not really sure what you are trying to do here, but it seems you are making things way harder than need be. In essence, it seems that you need to work with a two-dimensional array. So why not just query the database and read the data into a 2-D array right off the bat rather than jump through all these extra hoops (i.e. functions to determine unique array values and such)?
So you code might look something like this:
$county_array = array()
while ($row = [YOUR DATABASE ROW FETCHING MECHANISM HERE]) {
$county_array[$row['county_name']][] = $row; // you can change $row here to whatever data you actually need to store.
}
$limit = 2500;
foreach ($county_array as $county_name => $county_array) {
$temp_array = array();
$i = 0;
foreach ($county_array as $item) {
$temp_array[] = $item;
$i++;
if ($i === $limit) {
// we reached file limit, so write it to file code omitted for this
$temp_array = array();
$i = 0;
}
}
if (count($temp_array) > 0) {
// there are still items in temp array so write them to file code omitted for this
}
}
If you actually order by country name in your query and detect for changes to the value when reading county names out (and thus starting a new file), you could actually write directly into files in your loop that reads from the DB saving yourself memory overhead.
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());
?>