0

I've got a csv file being delivered via ftp twice a day. I'm trying to write a php file to open this file, filter it by the category column, delete rows which don't have a certain term/terms in then save the file.

I've tried lots of variants of snippets of code found on the internet but can't for the life of me figure out how to get it to work.

I tried using a variant of the code found in this question but couldn't make it work in my scenario

Filter a csv file by a word or text using php

If it helps the csv file I am trying to edit is located here: http://accurateav.co.uk/sahara/saharafeed.csv

<?php
$file  = fopen('saharafeed.csv', 'r');

// You can use an array to store your search words, makes things more flexible.
// Supports any number of search words.
$words = array('casio');    
// Make the search words safe to use in regex (escapes special characters)
$words = array_map('preg_quote', $words);
$regex = '/'.implode('|', $words).'/i';

while (($line = fgetcsv($file)) !== FALSE) {  
    list($ExportDate, $ItemCode, $Manufacturer, $Model, $ProductName, $DealerPrice, $Stock, $RRP, $Category, $ShortDesc, $LongDesc, $Weightkg, $EAN, $NonStock, $LargePictureURL, $SpecSheet, $HiResPhoto1, $HiResPhoto2) = $line;

    if(preg_match($regex, $Category)) {
        echo "$ExportDate, $ItemCode, $Manufacturer, $Model, $ProductName, $DealerPrice, $Stock, $RRP, $Category, $ShortDesc, $LongDesc, $Weightkg, $EAN, $NonStock, $LargePictureURL, $SpecSheet, $HiResPhoto1, $HiResPhoto2<br />\n";
    }
}

?>

This is the code I have used so far to filter the category to only show products in the Casio category however when i run the script no results are shown even though there are numerous products under the casio category.

Community
  • 1
  • 1
Danny
  • 43
  • 1
  • 7
  • Well, we would like to see some attempts and some description of what doesn't work and why. This way, anyone could submit a complete application which also might not work. Not very helpful. – GolezTrol Jun 11 '14 at 11:20
  • But rather than thinking in terms of 'filtering' and 'deleting' rows, maybe you can generate a second file. Loop through the first, and only copy the rows you want to keep to the second file. Afterwards, delete the source file and rename the target file. Et voilá, – GolezTrol Jun 11 '14 at 11:21
  • @GolezTrol I've amended my original question to include the code I'm using so far to do the filtering section. – Danny Jun 11 '14 at 11:30
  • are you sure that casio is indeed in the category column? i've checked you csv, it seems casio always falls under the manufacturer column (which is column 3) – user1978142 Jun 11 '14 at 12:15
  • Well that's me feeling very stupid right now! – Danny Jun 11 '14 at 12:58

2 Answers2

2

I think your searching the wrong column. casio is inside the manufacturer column. You must search there instead. Consider this example:

$i = 0;
$manufacturer_key = null;
$needles = array('casio', 'nec', 'hitachi');
$results = array();
$columns = array();
if(($handle = fopen('saharafeed.csv', 'r')) !== false) {
    while(($data = fgetcsv($handle, 4096, ',')) !== false) {
        if($i == 0)  {
            // sets the key where column to search
            $columns = $data;
            $i++; $manufacturer_key = array_search('Manufacturer', $data);
        } else {
            foreach($needles as $needle) {
                if(stripos($data[$manufacturer_key], $needle) !== false) {
                    $results[] = $data;
                } 
            }   
        }
    }
    fclose($handle);
}

array_unshift($results, $columns);

echo '<pre>';
print_r($results);
echo '</pre>';

Sample Output for casio:

Array
(
    [0] => Array
        (
            [0] => ExportDate
            [1] => ItemCode
            [2] => Manufacturer
            [3] => Model
            [4] => ProductName
            [5] => DealerPrice
            [6] => Stock
            [7] => RRP
            [8] => Category
            [9] => ShortDesc
            [10] => LongDesc
            [11] => Weightkg
            [12] => EAN
            [13] => NonStock
            [14] => LargePictureURL
            [15] => SpecSheet
            [16] => HiResPhoto1
            [17] => HiResPhoto2
        )

    [1] => Array
        (
            [0] => 11/06/2014
            [1] => 1610044
            [2] => NEC
            [3] => 60003221
            [4] => NEC  NP14ZL
            [5] => 999
            [6] => 0
            [7] => 1348.65
            [8] => Projectors Accessories
            [9] => 2.97-4.79:1 Zoom Lens
            [10] => Replacement 2.97–4.79:1 Zoom Lens compatible with the following products:

... and many more

Put the results back into csv format:

$fp = fopen('file.csv', 'w');

foreach ($results as $row) {
    fputcsv($fp, $row);
}

fclose($fp);
user1978142
  • 7,946
  • 3
  • 17
  • 20
  • If I wanted to save the file containing just the results found using Casio how would I do this? So it opens the original file, searches for casio then saves the original file in the same format but just containing those? If I wanted to include NEC for example could I just add this to needle? or would this require a total recode? Basically I just want to set it so it searches for predefined manufacturers and only leaves these in the file, thus filtering the original table (if that makes sense) – Danny Jun 11 '14 at 13:00
  • @Danny do you mean created another csv containing only casio entries? in my example, i used `$results` as the container for all casio entries. you can use `$results` and save it on another csv. use [**`fputcsv`**](http://www.php.net//manual/en/function.fputcsv.php) – user1978142 Jun 11 '14 at 13:03
  • Sorry edited my initial comment to explain further what I meant, Basically I'm trying to take a feed from a supplier and filter out the products I don't want by manufacturer so either overwrite the original file with the filtered data or create a new file in the same csv structure as the original – Danny Jun 11 '14 at 13:06
  • @Danny so in this particular case, `casio` was just an example? if you want another set of values, just change ofcourse the string inside the `array_search()` with another column name that you want, and also change the `$needle` that you want to search for, with regards to the structure, its basically still the same, its just filtered, its much better to create new a new copy. – user1978142 Jun 11 '14 at 13:12
  • Yep in this case casio was just one of the manufacturers I want to search for, the search terms will always be manufacturers. Am I able to search for (for example) Casio, NEC, Hitachi all in the same 'query'? – Danny Jun 11 '14 at 13:14
  • @Danny if you want such feature, that you can search multiple manufacturers, you may really need to loop them, check the edit, the first code just checks for a single string, the new edit uses an array so that it can hold many values – user1978142 Jun 11 '14 at 13:19
  • That's exactly what I was looking for! So even if I wanted to search by 10 different manufacturers I'd just enter those in to the array and it would run until each item had been checked? One last quick question, if I save the output to a new file, will this retain the headers? I have an import running from WooCommerce which decodes the information by their headers. Thank you for your continued help! – Danny Jun 11 '14 at 13:24
  • @Danny yes it should work even on 10 values, just feed the array with your needed values to searched. i edited the answer again, basically i just added a `$columns` array which holds the columns, after the filtering is complete, it is prepended on the final result (using `array_unshift()`), thus adding it on the beginning of the resultant array, then you can create the csv again. – user1978142 Jun 11 '14 at 13:35
  • Amazing! Again I cannot thank you enough for your help with this! Now just to figure out the output. Have a great day! – Danny Jun 11 '14 at 13:38
  • @Danny just a tip, follow the link that i gave you about `fputcsv()`, examples there should be fairly straightforward and should be easy to implement. Your welcome! Glad to help – user1978142 Jun 11 '14 at 13:41
  • I know I said one last question before but... I've had a look at the example link you sent me and had a play around but when I attempt to save it comes up with an error saying about expecting parameter to to be a string and an array being supplied. Had a look around google and it seems the fact it is multi-dimensional throws a spanner into the works. Any pointers? Will continue to have a look and try and figure it out – Danny Jun 11 '14 at 14:05
  • What I've tried is: `$fh = fopen('blank.csv', 'w'); // write out the headers fputcsv($fh, array_keys($results)); // write out the data for ($i = 0; $i < count($data['results']); $i++) { $temp = array($data['results'][$i], $data['columns'][$i]); fputcsv($fh, $temp); }` This outputs the numbers 1-163 which I'm assuming is the number of results – Danny Jun 11 '14 at 14:12
  • @Danny simple loop is all you need: `$fp = fopen('file.csv', 'w'); foreach ($results as $row) { fputcsv($fp, $row); } fclose($fp);` – user1978142 Jun 11 '14 at 14:32
  • As always, trying to overcomplicate things where something simple works! Thank you again! – Danny Jun 11 '14 at 14:34
0
Remove the line matching by a regular expression (by eliminating one containing digital   characters, at least 1 digit, located at the end of the line):

sed '/[0-9/][0-9]*$/d' filename.txt

user3535130
  • 316
  • 2
  • 5
  • Sorry I'm slightly unclear what I'm removing/replacing, I'm relatively new to PHP – Danny Jun 11 '14 at 11:51
  • its basically linux command, i hope your server is linux env. here you can get an idea - http://en.kioskea.net/faq/1451-sed-delete-one-or-more-lines-from-a-file – user3535130 Jun 11 '14 at 11:59
  • Where would this be placed in the file? – Danny Jun 11 '14 at 12:00
  • code is working fine. its returning the elements you have selected in Array $words = array('Cables'); – user3535130 Jun 11 '14 at 12:40
  • I realised with thanks to a comment above that I'd made a mistake and was searching under the wrong column. Thank you for your help! – Danny Jun 11 '14 at 13:15