I'm incredibly new to php so please bear with me and help me learn. I have a .csv file that's 33 lines long (including titles) and 4 columns wide. I want to read that data into an array so I can begin to sort and manipulate it.
What is the best course of action for doing so? Code snippits are the best way for me to learn code as I can read, interpret, use and then spit back questions I may have.
Using fgetcsv returns an array from a csv file line. To see it exploded you run put your returned array into a print_r() function. To see that in a pretty-print type view you can wrap it in <pre> tags
<?php
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
echo "<pre>".print_r($data)." <br /></pre>";
}
fclose($handle);
}
?>
That should be a good start.
http://php.net/manual/en/function.fgetcsv.php
Related
I was wondering if there was a way to find specific parts of a csv filename and use that specific part when writing a new file (another CSV). I have some codes below:
$files = glob("C:\readonly\csvs\%.csv");
$filename = "C:\newcsvs\Dated_File.csv";
$newFile = fopen($filename, "w");
foreach($files as $file)
{
if(($handle = fopen($file, "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
fputcsv($newFile, [$data[0], $data[1]]);
}
}
fclose($handle);
fclose($newFile);
}
So let's say for example I have a CSV with the file name of Johnson_report[2019-02-05]-[2019-02-15].csv and I wanted to take the end portion [2019-02-15] and append that to the new CSV when it's written how would I go about doing that? Specifically, each new CSV that I would make would have to take whatever the file's specific ending characters (they will always end in a specific date range) and use that ending date in the name of the new CSV. I understand that glob can find specific patterns but how would I use it in this manner?
Thanks to Jeto, preg_match & the renaming functions were the answers. Used preg_match to find the dates, then appended each match to the file name with the rename function after the file was closed while within the foreach loop.
I have a CSV that is downloaded from the wholesaler everynight with updated prices.
What I need to do is edit the price column (2nd column) and multiply the current value by 1.3 (30%).
My code to read the provided CSV and take just the columns I need is below, however I can't seem to figure out how to edit the price column.
<?php
// open the csv file in write mode
$fp = fopen('var/import/tb_prices.csv', 'w');
// read csv file
if (($handle = fopen("var/import/Cbl_4036_2408.csv", "r")) !== FALSE) {
$targetColumns = array(1, 2, 3); // get data from the 1st, 4th and 15th column
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$targetData = array(); // array that hold target data
foreach($targetColumns as $column){ // loop throught the targeted columns array
if($column[2]){
$data[$column] = $data[0] * 1.3;
}
$targetData[] = $data[$column]; // get the data from the column
}
# Populate the multidimensional array.
$csvarray[$nn] = $targetData; // add target data to csvarray
// write csv file
fputcsv($fp, $targetData);
}
fclose($handle);
fclose($fp);
echo "CSV File Written Successfully!";
}
?>
Could somebody point me in the right direction please, explaining how you've worked out the function too so I can learn at the same time.
You are multiplying your price column always as - $data[0] * 1.3.
It may be wrong here.
Other views:
If you are doing it once in a lifetime of this data(csv) handling, try to solve it using mysql itself only. Create the table similar to the database, import the .csv data into that mysql table. And then, SQL operate as you want.
No loops; no coding, no file read/write, and precise control over what you want to do with UPDATE. You just need to be aware of the delimiters (line separators eg. \r\n, column separators (eg. comma or tab or semicolon) and data encoding in double/single-quotes or not)
Once you modify your data, you can export it back to csv again.
If you want to handle the .csv file itself, open it in one connection (read only mode), and write to another file - saving the original data.
you say that the column that contains the price is the second but then use that index with zero. anyway the whole thing can be easier
$handle = fopen("test.csv", "r");
if ( $handle !== FALSE) {
$out = "";
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$data[1] = ((float)$data[1] * 1.3);
$out .= implode(";",$data) . "\n";
}
fclose($handle);
file_put_contents("test2.csv", $out);
}
this code open a csv file with comma as separator.
than read every line and for every line it's multiplies the second coloumn (index 1) for 1.3
this line
$out .= implode(";",$data) . "\n";
generate a line for new csb file. see implode on the officile documentation ...
after I close the connection to the file. and 'useless to have a connection with two files when you can do the writing of the second file in one fell swoop. the thing is true for small files
I'm trying my best to learn PHP and hack things out myself. But this part has me stuck.
I have two CSV files with hundreds of rows each.
CSV 1 looks like this:
name, email, interest
CSV 2 looks like this:
email only
I'm trying to write a script to compare the two files looking for duplicates. I only want to keep the duplicates. But as you can see, CSV 2 only contains an email. If an email in CSV 1 DOES NOT EXIST in CSV 2, then the row containing that email in CSV 1 should be deleted.
The end result can either overwrite CSV 1 or create a fresh new file called "final.csv"... whatever is easiest.
I would be grateful for the help.
I tried something along these lines with no luck:
egrep -v $(cat csv2.csv | tr '\n' '|' | sed 's/.$//') csv1.csv
and
grep -v -f csv22.csv csv1.csv >output-file
cheers,
marc
Here is a script that will loop through both files and output a 3rd file where email addresses in file2 are found in file1.
if (($file3 = fopen("file3.csv", "w")) !== FALSE) {
if (($file1 = fopen("file1.csv", "r")) !== FALSE) {
while (($file1Row = fgetcsv($file1)) !== FALSE) {
if (($file2 = fopen("file2.csv", "r")) !== FALSE) {
while (($file2Row = fgetcsv($file2)) !== FALSE) {
if ( strtolower(trim($file2Row[0])) == strtolower(trim($file1Row[1])) )
fputcsv($file3, $file1Row);
}
fclose($file2);
}
}
fclose($file1);
}
fclose($file3);
}
Couple of notes:
You may need to provide some additional arguments to fgetcsv, depending on how your csv is structured (e.g. delimiter, quotes)
Based on how you listed the contents of each file, this code reads the 2nd column of file1, and the 1st column of file2. If that's not really how they are positioned, you will need to change the number in the bracket for $file1Row[1] and $file2Row[0]. Column # starts at 0.
Script is current set to overwrite if file3.csv exists. If you want it to append instead of overwrite, change the 2nd argument of the $file3 fopen to "a" instead of "w"
Example:
file1.csv:
john,john#foobar.com,blah
mary,mary#blah.com,something
jane,jan#something.com,blarg
bob,bob#test.com,asdfsfd
file2.csv
mary#blah.com
bob#test.com
file3.csv (generated)
mary,mary#blah.com,something
bob,bob#test.com,asdfsfd
Solved! The problem was with Mac line breaks. Look at the code below to see the additions at the beginning and end of the code to fix that problem. Thank you Crayon Violent for all of your help!
ini_set('auto_detect_line_endings',TRUE);
if (($file3 = fopen("output.csv", "w")) !== FALSE) {
if (($file1 = fopen("dirty.csv", "r")) !== FALSE) {
while (($file1Row = fgetcsv($file1)) !== FALSE) {
if (($file2 = fopen("clean.csv", "r")) !== FALSE) {
while (($file2Row = fgetcsv($file2)) !== FALSE) {
if ( strtolower(trim($file2Row[0])) == strtolower(trim($file1Row[1])) )
fputcsv($file3, $file1Row);
}
fclose($file2);
}
}
fclose($file1);
}
fclose($file3);
}
ini_set('auto_detect_line_endings',FALSE);
I am trying to use a function much like this.....
$file = fopen("/tmp/$importedFile.csv","r");
while ($line = fgetcsv($file))
{
$csv_data[] = $line;
}
fclose($file);
...to load CSV values. This is gravy but now I wish to select individual columns by their array number. I believe I want to select it with something like this, but cannot find any clarity.
$csv_data[2] = $line;
This however just shows second (third) row of data rather than column.
Regards
Do you need the whole file in memory or will you be processing the lines individually?
Processing individually:
$line is already an array. If you want the 3rd column, use $line[2]
Processing after reading the whole file:
$csv_data[$lineNo][$columnNo]
$inputfiledelimiter = ",";
if (($handle = fopen($PathOfCsvFile, "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 0, $inputfiledelimiter)) !== FALSE)
{
//get data from $data
}
}
Well, your CSV file is now split up in lines, that is all.
No concept of columns yet in that structure.
So you need to split the lines into columns.
Or, much better, let PHP do that for you: Have a look at fgetcsv() and the associated functions:
http://nl.php.net/manual/en/function.fgetcsv.php
Trying to use filegetcsv to parse a CSV file and do stuff with it, using the following code found all over the Internet, including the PHP function definition page:
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
print_r($data);
}
fclose($handle);
}
But the code gives me an infinite loop of warnings on the $data = line:
PHP Warning: fgetcsv() expects parameter 1 to be resource, boolean given in...
I know the file I'm opening is a valid file, because if I add a dummy character to the file name I get a different error and no loop.
The file is in a folder with full permissions.
I'm not using a CSV generated by an Excel on Mac (there's a quirky error there)
PHP version 5.1.6, so there should be no problem with the function
I know the file's not too big, or malformed, because I kept shrinking the original file to see if that was a problem and finally just created a custom file in Notepad with nothing more than two lines like:
Value1A,Value1B,Value1C,Value1D
Still looping and giving no data. Here's the full code I'm working with now (using a variable that's greater than the number of lines so I can prove that it would loop infinitely without actually giving my server an infinite loop)
if ($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r') !== FALSE) {
while ((($data = fgetcsv($handle, 1000, ',')) !== FALSE) && ($row < 10)) {
print_r($data);
$row++;
}
fclose($handle);
}
So I really have two questions.
1) What could I possibly be overlooking that is causing this loop? I'm half-convinced it's something really "face-palm" simple...
2) Why is the recommended code for this function something that can cause an infinite loop if the file exists but there is some unknown problem? I would have thought the purpose of the !== FALSE and so forth would be to prevent that kind of stuff.
There's no question about what's going on here: the file is not opened successfully. That's why $handle is a bool instead of a resource (var_dump($handle) to confirm this yourself).
fgetcsv then returns null (not false!) because there's an error, and your test doesn't pick this up because you are testing with !== false. As the documentation states:
fgetcsv() returns NULL if an invalid handle is supplied or FALSE on
other errors, including end of file.
I agree that returning null and false for different error conditions is not ideal, and furthermore that it's against the precedent established by lots of other functions, but that's just how it is (and things could be worse). As things stand, you can simply change the test to
while ($data = fgetcsv($handle, 1000, ","))
and it will work correctly in both cases.
Update:
You are the victim of assignment inside an if condition:
if ($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r') !== FALSE)
should have been
// wrap the assignment to $handle inside parens!
if (($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r')) !== FALSE)
I 'm sure you understand what went wrong here. This is the reason why I choose to never, ever, make assignments inside conditionals. I don't care that it's possible. I don't care that it's shorter. I don't even care that sometimes it's quite less "elegant" to write the loop if the assignment is taken out. If you value your sanity, consider doing the same.
$row = 1;
if (($handle = fopen($_FILES['csv-file']['tmp_name'], "r")) !== FALSE) {
$data = fgetcsv($handle , 1000 , ",");
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);
}
Try given Code Snippet once,because as i have noticed you are missing some important things in your code.