I think I need a second pair of eyes on this one. For the life of me I can't figure out why my SQL INSERT query is running twice every iteration:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($current_row == 1 || $current_row == 2) {
$num = count($data);
//echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
//echo $data[$c] . "<br />\n";
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1])); }
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
exit; }
}
}
$current_row++;
}
fclose($handle);
}
Well, I probably should have put forth a little more effort before asking for assistance. I was able to fix this by adding a row reset counter in the loop:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($current_row == 1 || $current_row == 2) {
$row_reset = 0;
$num = count($data);
//echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
//echo $data[$c] . "<br />\n";
if ($row_reset == 0) {
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1])); }
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
exit; }
}
$row_reset++;
}
}
$current_row++;
}
fclose($handle);
}
I'm still curious if there is a better way.
I looks like you were using some code to iterate through your columns, but actually only have two, containing the sku and prod ($data[0] and $data[1].) If that is the case, then you don't need the for loop inside. (BTW, it was that loop that was causing the query to be executed twice, as the query was inside it.) It also looks like you have two counters going for the row (current_row and row) so those can be combined. If you are using the if ($currentRow == 1... statement to ignore the header on row 0 and then only process 2 rows, you will want to switch it to if ($currentRow > 0) when you are ready to run the whole spreadsheet. Using break in the catch clause instead of exit will cause the code to drop out of the while loop and hit the fclose statement:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
$currentRow = 0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($currentRow == 1 || $currentRow == 2) {
$num = count($data);
//echo "<p> $num fields in line $currentRow: <br /></p>\n";
//echo "<p> The data for this row is: " . $data[0] . " " . $data[1] . "\n";
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1]));
}
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
break;
}
}
$currentRow++;
}
fclose($handle);
}
Related
I'm writing php code to parse a csv file. I have to validate the basic data type for all the fields in the csv fileds and should throw an instance of a CsvParserException if there is any broken data in the csv file. I've given a generic exception but I want to give a custom exception which is an instance of CsvParserException.
Below is my code. I'm not sure how to to properly handle this.
<?php
namespace app;
class CsvParser{
public function parse() {
$row = 1;
$flag = true;
if (($handle = fopen("file.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
echo $num;
$row++;
if($flag) { $flag = false; continue; } // this is to skip the first line
for ($c=0; $c < $num; $c++) {
echo "data[0] is = ". $data[0] . " data[c] is = ". $data[$c]. " <br />\n";
if(!((isset($data[0])) && (is_numeric($data[0])))) {
throw new \Exception('Id is not valid');
}
if(!((isset($data[1])) && (is_string($data[1])))) {
throw new \Exception('This is not a valid string. ');
}
if(!((isset($data[2])) && (is_string($data[2])))) {
throw new \Exception('This is not a valid string. ');
}
$date = strtotime($data[3]);
$splitData = explode('|', $data[4]);
foreach($splitData as $value) {
if(!((isset($value)) && (is_numeric($value)))) {
throw new \Exception('Integers is not valid');
}
}
}
}
fclose($handle);
}
}
}
?>
Can someone please help ?
I need to replace a lot of data in csv and after changing all things i want it saved to a new csv file.
i can read the csv with the code from php.net but i can't get it to work saving the new file. i have this
$row = 0;
if (($handle = fopen("original.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 20000, ";")) !== FALSE) {
$num = count($data);
$cat_alt = ['cold', 'hot', ... and so on...];
$cat_neu = ['kalt', 'heiß', ...und so weiter...];
echo "<p> $num Felder in Zeile $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
$output = str_replace($cat_alt, $cat_neu, $data[$c] . "<br />\n");
echo $output;
}
}
}
$fp = fopen('changed.csv', 'w');
foreach ($row as $rows) {
fputcsv($fp, $rows);
}fclose($fp);
You have two options:
Use n array
$rows = []
...
$rows[] = str_replace($cat_alt, $cat_neu, $data[$c] . "\n");
...
fputcsv($fp, $rows);
Open the output file beforehand and write to it as you process the data
$fp = fopen('changed.csv', 'w');
if (($handle = fopen("original.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 20000, ";")) !== FALSE) {
$num = count($data);
$cat_alt = ['cold', 'hot', ... and so on...];
$cat_neu = ['kalt', 'heiß', ...und so weiter...];
echo "<p> $num Felder in Zeile $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
fputs($fp, str_replace($cat_alt, $cat_neu, $data[$c] . "<br />\n"));
}
}
}
fclose($fp);
This is the standard code on php.net:
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
Let's assume that test.csv has 3 rows with:
cell11,cell12,cell13
cell21,cell22,cell23
cell31,cell32,cell33
Is it possible to use a foreach loop instead of the while used here and still get the values inside test.csv, for further use?
The code above gives this result:
3 fields in line 1:
cell11
cell12
cell13
3 fields in line 2:
cell21
cell22
cell23
3 fields in line 3:
cell31
cell32
cell33
This is what I have tried:
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
// while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// $num = count($data);
// echo "<p> $num fields in line $row: <br /></p>\n";
// $row++;
// for ($c=0; $c < $num; $c++) {
// echo $data[$c] . "<br />\n";
// }
// }
foreach(($data = fgetcsv($handle, 1000, ",")) as $field){
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
And the result:
3 fields in line 1:
cell11
cell12
cell13
3 fields in line 2:
cell11
cell12
cell13
3 fields in line 3:
cell11
cell12
cell13
This:
foreach(($data = fgetcsv($handle, 1000, ",")) as $field){ ...
Passes the data from fgetcsv to the new variable $data which doesn't make sense in this case. You can just write this:
foreach (fgetcsv($handle, 1000, ",") as $field) { …
But to explain why foreach doesn't work:
As fget (and thus fgetcsv) is a function it does not work as an array, it just returns one, namely the next line in the file.
The foreach example above just gets the first line from that function and iterates over it. This means you iterate over each column of the first line.
I have two very small CSV files that I want to load into array and compare each row and their individual cells, and if there is a change in any cell highlight it.
At the moment I am writing a script to load files and display these onto the browser as they appear on the files.
CSV structure:
My PHP Code:
<?php
$row = 1;
$row2 = 1;
if (($file = fopen("Workbook1.csv", "r")) !== FALSE && ($file2 = fopen("Workbook2.csv", "r")) !== FALSE ) {
while (($data = fgetcsv($file, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row Orginal File: <br /></p>\n";
$row++;
for ($i=0; $i < $num; $i++) {
echo $data[$i] . "<br />\n";
}
while(($data2 = fgetcsv($file2, 1000 , ",")) !== FALSE){
$num2 = count($data2);
echo "<p> $num2 fields in line $row2 Updated File: <br /></p>\n";
$row2++;
for ($x=0; $x < $num2; $x++) {
echo $data2[$x] . "<br />\n";
}
}
}
fclose($file);
fclose($file2);
}
?>
Browser Result:
Not to sure why the Array is structured like above image as i understand fgetcsv() read line by line.
Any one can see my my stake in code..?
You are not closing the first while loop in the right place.
Try this
<?php
$row = 1;
$row2 = 1;
if (($file = fopen("Workbook1.csv", "r")) !== FALSE && ($file2 = fopen("Workbook2.csv", "r")) !== FALSE ) {
while (($data = fgetcsv($file, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row Orginal File: <br /></p>\n";
$row++;
for ($i=0; $i < $num; $i++) {
echo $data[$i] . "<br />\n";
}
} // end first while loop
while(($data2 = fgetcsv($file2, 1000 , ",")) !== FALSE){
$num2 = count($data2);
echo "<p> $num2 fields in line $row2 Updated File: <br /></p>\n";
$row2++;
for ($x=0; $x < $num2; $x++) {
echo $data2[$x] . "<br />\n";
}
}
fclose($file);
fclose($file2);
}
?>
After reading this enter link description here
I managed to fix it by adding this line of code at the top of the file before fopen()
ini_set('auto_detect_line_endings',TRUE);
If you need to set auto_detect_line_endings to deal with Mac line
endings, it may seem obvious but remember it should be set before
fopen, not after:
Having this fixers how can i Compare the values between these two files..?
I want to take a text file formatted like so:
*note I can change the format of the stored messages, basically there are delimiters and different lines
;68.229.164.10:4/5/2013:Hello
;71.73.174.13:4/6/2013:Oh Hey
(;IPADDRESS:TIMESTAMP:MESSAGE)
and put it in a table that looks like so:
IP Time Message
68.229.164.10 4/6/2013 Hello
71.73.174.13 4/6/2013 Oh Hey
I prefer to use something like the following:
http://php.net/manual/en/function.fgetcsv.php
And then format the output accordingly.
From Example 1 on the above referenced page:
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
so, you could do something like this...
<?php
$row = 1;
if (($handle = fopen("path_to_your_data_file", "r")) !== FALSE) {
echo '<table>';
echo '<tr><td></td>IP<td>Time</td><td>Message</td></tr>';
while (($data = fgetcsv($handle, 1000, ":")) !== FALSE) {
$num = count($data);
$row++;
if ($num > 2) {
echo '<tr>';
for ($c=0; $c < $num; $c++) {
echo '<td>'.$data[$c].'</td>';
}
echo '</tr>';
}
}
echo '</table>';
fclose($handle);
}
?>
$a=";68.229.164.10:4/5/2013:Hello
;71.73.174.13:4/6/2013:Oh Hey";
preg_match_all('{;(.*?):(.*?):(.*)}',$a,$d);
//set th
$d[0][0]='IP';
$d[0][1]='TIME';
$d[0][2]='Message';
$table = '<table>'.PHP_EOL;
foreach($d AS $tr){
$row = PHP_EOL;
foreach($tr AS $td){
$row .= "<td>{$td}</td>".PHP_EOL;
}
$table .= "<tr>{$row}</tr>".PHP_EOL;
}
$table .= "</table>".PHP_EOL;
echo $table;