Related
I have a PHP code that is supposed to save values fro a CSV file into a MySql database table. Everything works fine except that only the first row of the CSV is added. Here's the code:
<?php
public function saveProductsFromCsv($productId, $val) {
$productId = (int) $productId;
$data = array();
$fieldNames = $this->_config->getCsvColumnNames();
array_shift($fieldNames);
$numberOfFields = count($fieldNames);
$lines = explode("\n", $val);
foreach ($lines as $line) {
$line = trim($line);
if (empty($line))
continue;
$values = explode(',', $line);
if (count($values) != $numberOfFields){
throw new Exception();
return;
}
$make = trim($values[0]);
$model = trim($values[1]);
$yearFrom = (int) $values[2];
$yearTo = (int) $values[3];
$engine = trim($values[4]);
if ($yearFrom > 0){
if ($yearFrom < 1950){
$yearFrom = 1950;
} elseif ($yearFrom > 2030){
$yearFrom = 2030;
}
}
if ($yearTo > 0){
if ($yearTo < 1950){
$yearTo = 1950;
} elseif ($yearTo > 2030){
$yearTo = 2030;
}
}
$data[] = array($productId, $make, $model, $yearFrom, $yearTo, $engine);
}
if (count($data) > 0){
$this->saveValues($data);
}
}
public function saveValues($data)
{
$valuesStr = '';
foreach ($data as $values){
$cell = '';
foreach ($values as $value)
$cell .= ",'" . esc_sql(trim($value)). "'";
$valuesStr .= ($valuesStr != '' ? ',' : '') . "(NULL{$cell})";
}
$this->_wpdb->query("INSERT IGNORE INTO {$this->_mainTable} VALUES {$valuesStr}");
}
?>
Below is the CSV:
product_sku,make,model,year_from,year_to,engine
63118,Toyota,FJ Cruiser,2000,2008,V6 4.7L 2UZ-FE 20R/22R 1st Gen FJ Cruiser
28216,Toyota,GX470,1992,1997,V8 4.7L 2UZ-FE GX470
62687,Toyota,Land Cruiser,1998,2007,V8 4.7L 2UZ-FE 100-Series
28485,Toyota,Land Cruiser,2007,2018,V8 5.7L 3UR-FE 200-Series
Incidentally, if I use this:
product_sku,make,model,year_from,year_to,engine
63118,Toyota,FJ Cruiser,2000,2008,engine1
28216,Toyota,GX470,1992,1997,engine2
62687,Toyota,Land Cruiser,1998,2007,engine3
28485,Toyota,Land Cruiser,2007,2018,engine4
everything gets inserted fine. I think the problem is with the last column because if I use the same values in the last column in the second or third columns, everything works fine.
Never mind, I've solved it. The problem was with the encoding of the CSV file. I changed it to UTF-8 and everything is working fine.
I have text file
name,name1
willhaveishere1
name,name2
willhaveishere2
name,name3
willhaveishere3
i want read it and return like that
$nn = name1
$ss = willhaveishere1
with my code i get only name1
my code is
$file1 = "file.txt";
$file = file($file1);
$count = count($file);
if($count > 0) {
$i = 1;
foreach($file as $row) {
$n = strstr($row, 'name,');
$cc = array("name,");
$dd = array("");
$nn = str_replace($cc, $dd, $n);
echo $nn;
$i++; } }
This is probably what you need
if($count > 0) {
foreach($file as $row) {
$pos = strpos($row, ',');
if($pos !== false){
echo substr($row, $pos + 1);
$nn[] = substr($row, $pos + 1);
} else {
echo $row;
$ss[] = $row;
}
}
}
EDIT
Yes, just loop through, but make sure both $nn and $ss has same count, which is depending on your file.
Also Note: mysql_* functions has been deprecated, so please use mysqli or PDO instead
$count = count($nn);
for($i=0; $i < $count; $i++){
$sql = "INSERT INTO users(name, line) VALUES('$nn[$i]', '$ss[$i]')"; mysql_query($sql);
}
EDIT 2
try this example:
$file = array(
0 => 'name,name1',
1 => 'willhaveishere1',
2 => 'name,name2',
3 => 'willhaveishere2',
4 => 'name,name3',
5 => 'willhaveishere3'
);
$count = count($file);
if($count > 0) {
foreach($file as $row) {
$pos = strpos($row, ',');
if($pos !== false){
$nn[] = substr($row, $pos + 1);
} else {
$ss[] = $row;
}
}
}
echo '<pre>';
$count = count($nn);
for($i=0; $i < $count; $i++){
$sql = "INSERT INTO users(name, line) VALUES('$nn[$i]', '$ss[$i]');";
echo $sql.PHP_EOL;
}
You can try this straightforward method:
if($fh = fopen("file.txt","r")){
$nameBefore = false;
//loop through every line of your file
while (!feof($fh)){
$line = fgets($fh);
//check if the name was detected in previous line
if ($nameBefore !== false)
{
//you have the set of name and line, do what you want
echo $nameBefore . ': ' . $line . '<br />';
$nameBefore = false;
}
else
{
//see if the line is made of two coma separated segments and the first one is 'name'
//Remember the name for the next line
$parts = explode(',', $line);
if (count($parts) == 2 && $parts[0] == 'name')
$nameBefore = $parts[1];
}
}
fclose($fh);
}
One option is to use strpos to find the first occurrence of the character in the line, and if found remove everything from the line before that position. This way you are left with only the part of the line you are interested in.
Code:
$character = ',';
$fileHandle = fopen('file.txt', 'r');
while (!feof($fileHandle)) {
// Retrieve the line from the file
$line = fgets($fileHandle);
// If the line contains the character
// Remove everything before the character
$charPos = strpos($line, $character);
if ($charPos !== false) {
$line = substr($line, $charPos + 1);
}
// Do something with the remainder of the line
echo $line . PHP_EOL;
}
fclose($fileHandle);
Output:
name1
willhaveishere1
name2
willhaveishere2
name3
willhaveishere3
If you wish to retrieve the following line, simply do another retrieve line call in your loop:
while (!feof($fileHandle)) {
// Retrieve two lines in one loop iteration
$lineOne = fgets($fileHandle);
$lineTwo = fgets($fileHandle);
}
Making sure to only apply the comma replace part on the first line. This can lead to problems though if your data is... inconsistent.
Hope this helps.
I can't figure out a way to do this and I really bad with working with arrays so I hope someone can help me.
I have array $stuck that just contains names, like this
$stuck = array('Daniel','Alex','alfredo','dina');
I am using sort to put the names in alphabetical order, like this
sort($stuck);
Now the thing is I want to put this array into a csv or excel file so the first letter of name will be the title and all the names with this letter will be under this title.
This is an example of what I am trying to accomplish
Here try this. I added comments between the code.
$csvArray = array();
$nameArray = array('Daniel','Alex','alfredo','dina');
//Create an array that can be used for creating the CSV
foreach($nameArray as $name)
{
$firstLetter = strtoupper(substr($name, 0,1));
$csvArray[$firstLetter][] = $name;
}
//Determine the subarray which have the must rules
$maxRuleCount = 0;
foreach($csvArray as $firstLetter => $nameArray)
{
if(count($nameArray) > $maxRuleCount)
{
$maxRuleCount = count($nameArray);
}
}
//Create the first rule (letters)
$csvContent = implode(';', array_keys($csvArray));
$csvContent .= "\r\n";
//Loop through the CSV array and create rules of the names
for($i = 0 ; $i < $maxRuleCount ; $i++)
{
foreach($csvArray as $firstLetter => $nameArray)
{
$csvContent .= #$csvArray[$firstLetter][$i].';';
}
$csvContent .= "\r\n";
}
//The hole csv content is in the $csvContent variable now
//If you want to print it you need to add the text/plain header because of the \r\n new line characters
header("Content-Type:text/plain");
echo $csvContent;
Ouput is:
D;A
Daniel;Alex;
dina;alfredo;
<?php
$stuck = array('Daniel','Alex','Dina','durban','eigor','alfredo','dina');
// associate names with first letters in a new array
foreach ($stuck as $name) {
$first_letter = strtoupper( substr( $name, 0, 1 ) );
$new_name_array[ $first_letter ][] = $name;
}
// store the first letter list in an array and sort it
$first_letters = array_keys( $new_name_array );
sort( $first_letters );
// sort the name lists
foreach( array_keys( $new_name_array ) as $letter ) {
sort( $new_name_array[$letter] );
}
// output csv header row
echo "'".implode( "','", $first_letters )."'\n";
// output the CSV name rows
$i = 0;
while ( true ) {
$row = array();
$is_row = false;
foreach( $first_letters as $letter ) {
$row[] = $new_name_array[ $letter ][ $i ];
if( ! empty( $new_name_array[ $letter ][ $i ] ) ) $is_row = true;
}
if( ! $is_row ) exit;
echo "'" . implode( "','", $row ) . "'\n";
$i++;
}
?>
Outputs quoted CSV:
'A','D','E'
'Alex','Daniel','eigor'
'alfredo','Dina',''
'','dina',''
'','durban',''
<?php
$stuck = array('Daniel','Alex','alfredo','dina', 'eigor', 'durban');
sort($stuck);
$sortedNames = array();
$maxEl = 0;
foreach ($stuck as $name) {
$name = strtolower($name);
$sortedNames[$name{0}][] = $name;
$maxEl = count($sortedNames[$name{0}]) < $maxEl ? $maxEl : count($sortedNames[$name{0}]);
}
$headers = array_keys($sortedNames);
$finalArray = array($headers);
for($i = 0; $i < $maxEl; $i++) {
$tmpRow = array();
foreach ($sortedNames as $names) {
$tmpRow[] = isset($names[$i]) ? $names[$i] : '';
}
$finalArray[] = $tmpRow;
}
$file = fopen("names.csv","w");
foreach ($finalArray as $line)
{
fputcsv($file,$line);
}
fclose($file);
Here is my attempt at this question:
$names = array('Daniel','Alex','alfredo','dina', 'eigor', 'falfoul', 'fiona');
natcasesort($names);
$columns = array();
foreach ($names as $name) {
$first = strtoupper(substr($name, 0, 1));
$columns[$first][] = $name;
}
// pad the columns so they all have the same number of rows
$maxRows = 0;
foreach ($columns as &$col) {
$numRows = count($col);
if ( $numRows > $maxRows) {
$maxRows = $numRows;
}
}
// pad the columns
foreach ($columns as &$column) {
$column = array_pad($column, $maxRows, '');
}
$firstLetter = array_keys($columns);
$numCols = count($firstLetter);
// transpose the columns array
$rows = array();
foreach ($columns as $csvCol) {
foreach ($csvCol as $k=>$n) {
$rows[$k][] = $n;
}
}
// pad the rows to ensure they all have the same number of
// columns
foreach ($rows as &$row) {
$row = array_pad($row, $numCols, '');
}
// add the title row to the rows
array_unshift($rows, $firstLetter);
$handle = fopen("names.csv", 'w');
foreach ($rows as $fRow) {
fputcsv($handle, $fRow);
}
I have an array with a list of domains sorted by domain extensions, like:
values[0] = "programming.ca";
values[1] = "Stackoverflow.ca";
values[2] = "question.com";
values[3] = "answers.com";
values[4] = "AASystems.com";
values[5] = "test.net";
values[6] = "hello.net";
values[7] = "apple.nl";
values[8] = "table.org";
values[9] = "demo.org";
How do I print this array, while automatically grouping it in groups with same domain extension and separated by the line break <br />, so the result will look like this?
programming.ca
Stackoverflow.ca
question.com
answers.com
AASystems.com
test.net
hello.net
apple.nl
table.org
demo.org
Try this.
$ext = "";
for($i = 0; $i < count($values); $i++) {
$parts = explode('.', $values[$i]);
$e = $parts[count($parts) - 1];
if(strcmp($parts[count($parts) - 1], $ext) != 0) {
$ext = $e;
echo '<br/>';
}
echo $values[$i].'<br/>';
}
try this if domain names are in order of domain extensions,
$values[0] = "programming.ca";
$values[1] = "Stackoverflow.ca";
$values[2] = "question.com";
$values[3] = "answers.com";
$values[4] = "AASystems.com";
$values[5] = "test.net";
$values[6] = "hello.net";
$values[7] = "apple.nl";
$values[8] = "table.org";
$values[9] = "demo.org";
$prev_ext = "";
foreach($values as $domain_name)
{
$arr_temp = explode(".", $domain_name);
$domain_ext = $arr_temp[1];
if($prev_ext!=$domain_ext)
{
echo '<br/></br/><br/>';
}
echo $domain_name."<br/>";
$prev_ext = $domain_ext;
}
UPDATE : 2
try this if domain names are not in order of their extensions
$values[0] = "programming.ca";
$values[1] = "AASystems.com";
$values[2] = "demo.org";
$values[3] = "answers.com";
$values[4] = "Stackoverflow.ca";
$values[5] = "test.net";
$values[6] = "hello.net";
$values[7] = "apple.nl";
$values[8] = "table.org";
$values[9] = "question.com";
$arr_domains = array();
foreach($values as $domain_name)
{
$arr_temp = explode(".", $domain_name);
$domain_ext = $arr_temp[1];
$arr_domains[$domain_ext][] = $domain_name;
}
foreach($arr_domains as $ext=>$arr_name)
{
echo "<br/><br/><b>".$ext."</b><br/>";
foreach($arr_name as $name)
{
echo $name."<br/>";
}
}
I edited to hopefully make naming clearer. Basically, explode each domain to get name.extension, then store each name in a dictionary of (extension,domainArray) pairs, then foreach entry in the dictionary, grab the domainArray, then foreach name in the domainArray, echo out the domain name . extension, then a line break, then another line break for every dictionary entry.
<?php
$values[0] = "programming.ca";
$values[1] = "Stackoverflow.ca";
$values[2] = "question.com";
$values[3] = "answers.com";
$values[4] = "AASystems.com";
$values[5] = "test.net";
$values[6] = "hello.net";
$values[7] = "apple.nl";
$values[8] = "table.org";
$values[9] = "demo.org";
$domainsList = [];
foreach ($values as $val) {
$valArr = explode(".", $val);
$name = $valArr[0];
$extension = $valArr[1];
if (isset($domainsList[$extension])) {
$domainsList[$extension][] = $name;
} else {
$domainsList[$extension] = [$name];
}
}
foreach ($domainsList as $extension => $domains) {
foreach ($domains as $domain) {
echo $domain . "." . $extension . "<br />";
}
echo "<br />";
}
Try this code.
$domian = array(
"programming.ca",
"Stackoverflow.ca",
"question.com",
"answers.com",
"AASystems.com",
"test.net",
"hello.net",
"apple.nl",
"table.org",
"demo.org");
$result;
foreach ($domian as $value) {
$arr = explode('.', $value);
$result[$arr[1]][] = $value;
}
print_r($result);
This code works perfectly except that it doesn't print the last 2 rows of my csv file:
This is the file:
603629,0,ATLV0008,"Vendor1",1942.60,11/04/2010,1942.60,9/1-9/30/10,EFT-JP
603627,2,ATLV0008,"Vendor1",1242.40,11/04/2010,1242.40,7/1-7/31/10,EFT-JP
600023,0,FLD4V0003,"Vendor2",1950.00,06/15/2010,1950.00,6/14/10 Request,EFT-JP
600024,0,FLD4V0003,"Vendor2",1800.00,06/15/2010,1800.00,6/14/10 Request,EFT-JP
603631,0,ATLV5066,"Vendor2",1000.00,11/09/2010,1000.00,11/4/10 Check Request,PM2
603647,0,ATLV5027,"DVendor3",2799.80,11/15/2010,2799.80,10/1-10/31/10 Bishop,PM2
603642,5,ATLV5027,"Vendor3",482.40,11/15/2010,482.40,10/1-10/18/10 Allen,PM2
603653,0,ATLV0403,"Vendor4",931.21,11/17/2010,931.21,9/1-9/30/10,EFT-JP
603661,0,ATLV0105,"Vendor5",26.75,11/19/2010,26.75,093139,PM2
603660,1,ATLV0105,"Vendor5",5.35,11/19/2010,5.35,093472,PM2
Here is the code: (It needs to display the sum of 2 rows with the same vendor before the actual rows)
if (($handle = fopen('upload/ATLANTA.csv', "r")) !== FALSE) {
while (($row_array = fgetcsv($handle, 1000, ","))) {
foreach ($row_array as $key => $val) {
$row_array[$key] = trim(str_replace('"', '', $val));
ob_flush();
}
$complete[] = $row_array;
ob_flush();
}
}
flush();
$prevVendor = '';
$sum = 0;
$venData = '';
if (isset($complete)) {
foreach ($complete as $key => $val) {
$venData .= "<br/>";
$currVendor = $complete[$key][3];
if ($currVendor != $prevVendor){
if ($prevVendor != NULL){
print "<br/>";
print $sum . "<br/>";
print $venData;
$sum = 0; $venData = '';
}
}
foreach ($val as $ikey => $ival){
if ($ikey != 1){
$venData .= $ival . ' ';
$prevVendor = $val[3];
}
}
if ($currVendor == $prevVendor){
$sum += $complete[$key][6];
}
}
}
I don't really understand your problem but if you want to get (and save it wherever you want) the sum of each vendors, you should do something like this :
$prevVendor = null;
$venData = '';
$sums = array();
if (isset($complete) && is_array($complete)) {
$lim = count($complete);
for ($key=0;$key<$lim;++$key) { // no need foreach for simple array
$venData .= "<br/>";
$currVendor = $complete[$key][3];
if ($currVendor != $prevVendor){
if ($prevVendor != null){
print "<br/>";
print $venData;
}
$venData = '';
$prevVendor = $currVendor;
$sums[$currVendor] = 0; // set the counter to 0
}
foreach ($complete[$key] as $ikey => $ival){
if ($ikey != 1){
$venData .= $ival . ' '; // is useful for you I guess
}
}
$sums[$currVendor] += $complete[$key][6]; // add amounts
}
}
if ($prevVendor != null){ // you need to do this to display the last record
print "<br/>";
print $venData;
}
var_export($sums); // check results
This can be some syntax errors ...