I am trying to create a application that will parse a CSV file of items, and do specific things for each item in the CSV file. I have the upload/parsing figured out, however, when I export it to Excel each CSV entry is duplicated in the worksheets. For example, if there were 4 entries in the CSV file, the first entry is duplicated 4 times, the second entry is duplicated 3 times, etc. I have look through documentation for days, and I am unable to locate where I am going wrong. Below is the code that is generating the XLSX file.
if (in_array($type,$csv_types)){
if (move_uploaded_file($tmp_name, $path)){
foreach ($csv as $locar){
foreach ($locar as $locid){
$locs[] = $locid;
$count = count($locs);
/*if ($i < $count - 1){
$objPHPExcel->createSheet();
$i++;
}*/
$xmls = array();
foreach ($locs as $locids){
$url = 'Link to XML API' . $locids;
$xmls[] = $url;
$objWorkSheet = $objPHPExcel->createSheet();
$objWorkSheet->setTitle($locids);
$objPHPExcel->setActiveSheetIndexByName($locids);
}
foreach ($xmls as $links){
$locations = explode("=", $links);
$row = 1;
//
$objPHPExcel->getActiveSheet()->setCellValue('A'.$row,'Location ID:' . $locations[1]);
$row++;
$objPHPExcel->getActiveSheet()->SetCellValue('A'.$row,'Database');
$objPHPExcel->getActiveSheet()->SetCellValue('B'.$row,'URL');
$row++;
$xml = simplexml_load_file($links);
foreach ($xml as $product){
foreach ($product->title as $item){
$dbtitle = str_replace(',',' ',$item);
$dblink = $product->link;
}
$objPHPExcel->setActiveSheetIndexByName($locations[1]);
$objPHPExcel->getActiveSheet()->SetCellValue('A'.$row,$dbtitle);
$objPHPExcel->getActiveSheet()->SetCellValue('B'.$row,$dblink);
$row++;
}
}
}
}
}
The Links that are generated by the code are only showing up in the correct worksheet (the first created worksheet for the entry in the csv). Any help would be greatly appreciated.
Try this...
if (in_array($type,$csv_types)){
if (move_uploaded_file($tmp_name, $path)){
foreach ($csv as $key => $locar){
$locs[] = $locid[$key];
$count = count($locs);
/*if ($i < $count - 1){
$objPHPExcel->createSheet();
$i++;
}*/
$xmls = array();
$url = 'Link to XML API' . $locids[$key];
$xmls[] = $url;
$objWorkSheet = $objPHPExcel->createSheet();
$objWorkSheet->setTitle($locids[$key]);
$objPHPExcel->setActiveSheetIndexByName($locids[$key]);
$locations = explode("=", $links[$key]);
$row = 1;
//
$objPHPExcel->getActiveSheet()->setCellValue('A'.$row,'Location ID:' . $locations[1]);
$row++;
$objPHPExcel->getActiveSheet()->SetCellValue('A'.$row,'Database');
$objPHPExcel->getActiveSheet()->SetCellValue('B'.$row,'URL');
$row++;
$xml = simplexml_load_file($links[$key]);
foreach ($xml as $product){
foreach ($product->title as $item){
$dbtitle = str_replace(',',' ',$item);
$dblink = $product->link;
}
$objPHPExcel->setActiveSheetIndexByName($locations[1]);
$objPHPExcel->getActiveSheet()->SetCellValue('A'.$row,$dbtitle);
$objPHPExcel->getActiveSheet()->SetCellValue('B'.$row,$dblink);
$row++;
}
}
}
}
Also can you post the $xml array (print_r)...
$xml = simplexml_load_file($links[$key]);
Related
I want to load csv file data to extract the urls from CSV and check for the title tag for all the urls and update the urls with corresponding title tags in a new csv. But while I try to add data to the csv all the urls are getting listed but only the title of the last url is displayed in the CSV. I have tried different ways to overcome this problem but unable to do so.
Here is my code:
<?php
ini_set('max_execution_time', '300'); //300 seconds = 5 minutes
ini_set('max_execution_time', '0');
include('simple_html_dom.php');
// if (isset($_POST['resurl'])) {
// $url = $_POST['resurl'];
if (($csv_file = fopen("old.csv", "r", 'a')) !== FALSE) {
$arraydata = array();
while (($read_data = fgetcsv($csv_file, 1000, ",")) !== FALSE) {
$column_count = count($read_data);
for ($c = 0; $c < $column_count; $c++) {
array_push($arraydata, $read_data[$c]);
}
}
fclose($csv_file);
}
$title = [];
foreach ($arraydata as $ad) {
$ard = [];
$ard = $ad;
$html = file_get_html($ard);
if ($html) {
$title = $html->find('title', 0)->plaintext;
// echo '<pre>';
// print_r($title);
}
}
$ncsv = fopen("updated.csv", "a");
$head = "Url,Title";
fwrite($ncsv, "\n" . $head);
foreach ($arraydata as $value) {
// $ar[]=$value;
$csvdata = "$value,$title";
fwrite($ncsv, "\n" . $csvdata);
}
fclose($ncsv);
I've changed the code so that you write the CSV file as you read the HTML pages. This saves having another loop and an extra array of titles.
I've also changed it to use fputcsv to write the data out as it sorts ot things like escaping values etc.
// Open file, using w to clear the old file down
$ncsv = fopen('updated.csv', 'w');
$head = 'Url,Title';
fwrite($ncsv, "Url,Title" . PHP_EOL . $head);
foreach ($arraydata as $ad) {
$html = file_get_html($ad);
// Fetch title, or set to blank if html is not loaded
if ($html) {
$title = $html->find('title', 0)->plaintext;
} else {
$title = '';
}
// Write record out
fputcsv($ncsv, [$value, $title]);
}
fclose($ncsv);
I was able to solve it finally.
Here is the updated code:
<?php
ini_set('max_execution_time', '300'); //300 seconds = 5 minutes
ini_set('max_execution_time', '0');
include('simple_html_dom.php');
// if (isset($_POST['resurl'])) {
// $url = $_POST['resurl'];
if (($csv_file = fopen("ntsurl.csv", "r", 'a')) !== FALSE) {
$arraydata = array();
while (($read_data = fgetcsv($csv_file, 1000, ",")) !== FALSE) {
$column_count = count($read_data);
for ($c = 0; $c < $column_count; $c++) {
array_push($arraydata, $read_data[$c]);
}
}
fclose($csv_file);
}
// print_r($arraydata);
$title=[];
$ncsv=fopen("ntsnew.csv","a");
$head="Website Url,title";
fwrite($ncsv,"\n".$head);
foreach($arraydata as $ad)
{
$ard = [];
$ard = $ad;
$html = file_get_html($ard);
if ($html) {
$title = $html->find('title', 0)->plaintext;
echo '<pre>';
print_r($title);
$csvdata="$ard,$title ";
fwrite($ncsv,"\n".$csvdata);
}
}
// fclose($ncsv);
I'm still at the first stage of learning. Here is my problem: I want to skip the first row of an Excel file to upload it into the database. I hope you can help me to solve this.
Here is the code:
$Reader = new SpreadsheetReader($targetPath);
$sheetCount = count($Reader->sheets());
for($i=0;$i<$sheetCount;$i++)
{
$Reader->ChangeSheet($i);
foreach ($Reader as $Row)
{
$period = "";
if(isset($Row[0])) {
$period = mysqli_real_escape_string($conn,$Row[0]);
}
$target = "";
if(isset($Row[1])) {
$target = mysqli_real_escape_string($conn,$Row[1]);
}
$achieved = "";
if(isset($Row[2])) {
$achieved = mysqli_real_escape_string($conn,$Row[2]);
}
$batch = "";
Use continue to skip processing for just the first row.
foreach ($Reader as $index => $Row) {
if ($index === 0) {
continue;
}
// process $Row
}
This assumes $Reader has a zero-based index.
First of all I load PHPExcel.php
Secondly, I am using this code:
$location = '/path/file.csv';
$inputFileType = 'CSV';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objPHPExcel = $objReader->load($location);
$worksheet = $objPHPExcel->getActiveSheet();
$list = array();
foreach ($worksheet->getRowIterator() as $row)
{
$rowIndex = $row->getRowIndex();
$cellValue = $worksheet->getCell('A'.$rowIndex)->getValue();
array_push($list, $cellValue);
}
$count = count($list);
for ($rowIndex = $count; $rowIndex != 1; $rowIndex--)
{
$cellValue = $worksheet->getCell('A'.$rowIndex)->getValue();
for ($i = $rowIndex - 2; $i != 0; $i--)
{
if ($list[$i] == $cellValue)
{
$worksheet->removeRow($rowIndex);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'CSV');
$objWriter->save($location);
break;
}
}
}
So, I am trying to remove the rows when there are duplicate values in the first column. The code does not work. When I first run it in putty, I have to wait for ages. I interrupt the process and then I run it again. Then it runs, but in my csv file I have wrong results (duplicates are 300 but I am getting -600 rows).
In order to read a CSV file you dont have to use PHPExcel. Instead you can use a native php code like this one:
<?php
// Array which will hold all analyzed lines
$uniqueEntries = array();
$dublicatedEntries = array();
$delimiter = ',';
$file = 'test.csv';
//Open the file
if (($handle = fopen($file, "r")) !== false) {
// read each line into an array
while (($data = fgetcsv($handle, 8192, $delimiter)) !== false) {
// build a "line" from the parsed data
$line = join($delimiter, $data);
//If the line content has ben discovered before - save to duplicated and skip the rest..
if (isset($uniqueEntries[$line])){
dublicatedEntries[] = $line;
continue;
}
// save the line
$uniqueEntries[$line] = true;
}
fclose($handle);
}
// build the new content-data
$contents = '';
foreach ($uniqueEntries as $line => $bool) $contents .= $line . "\r\n";
// save it to a new file
file_put_contents("test_unique.csv", $contents);
?>
This code is untested but should work.
This will give you a .csv file with all unique entries.
We are converting excel to CSV with every sheet. For example if a excel file has 5 sheets then we are converting 5 CSV file for every sheet.
Its working fine except one thing.
As we know excel sheet has some formulas for calculation like sum, Average etc..., So when we are converting them to CSV file, Then function is showing as it is, Their calculated value is not showing, which we can read as a excel sheet.
This is the function which we are using
function write_csv($filename,$definename){
$dir = "";
$file_arr = array();
array_push($file_arr, $filename);
// Make CSV File
$list = array();
foreach($file_arr as $val)
{
$arr_data = array();
// echo $val;
$objPHPExcel = PHPExcel_IOFactory::load($dir . $val);
// print_r($objPHPExcel->getSheetNames());exit;
$loadedSheetNames = $objPHPExcel->getSheetNames();
foreach($loadedSheetNames as $sheetIndex => $loadedSheetName) {
// echo $sheetIndex;
$objPHPExcel->setActiveSheetIndex($sheetIndex);
$fp = fopen($definename.'_'.$sheetIndex.'.csv', 'a');
$cell_collection = $objPHPExcel->getActiveSheet()->getCellCollection();
// print_r($cell_collection);
foreach($cell_collection as $cell)
{
$column = $objPHPExcel->getActiveSheet()->getCell($cell)->getColumn();
$row = $objPHPExcel->getActiveSheet()->getCell($cell)->getRow();
$data_value = $objPHPExcel->getActiveSheet()->getCell($cell)->getValue();
//header will / should be in row 1 only. of course this can be modified to suit your need.
// Skip Rows From Top if you have header in Excel then Change 0 to 1
if($row == 0)
{
$header[$row][$column] = $data_value;
}
else
{
$arr_data[$row]['row'] = $row;
$arr_data[$row][$column] = $data_value;
}
}
$data = $arr_data;
foreach($data as $val1)
{
$num_col = sizeof($val1) - 1; // get number of columns in Excel
break;
}
$lwrcol=array();
foreach($data as $val2)
{
$alphaArr = range('A','Z');
$colArr = range('A',$alphaArr[$num_col - 1]);
foreach($colArr as $col)
{
$lwrcol[$col] = isset($val2[$col]) ? utf8_decode($val2[$col]) : "";
fwrite($fp,$lwrcol[$col].",");
}
fwrite($fp,"\n");
}
// chmod(getcwd()."/file.csv", 0777);
fclose($fp);
}
}
}
Please tell me what we are doing wrong.
Complete Code:
http://pastebin.com/DaRBSpqP
I'm parsing some HTML with DOM/Xpath, with the ultimate goal of generating a .CSV file with the data I've grabbed with my queries.
The current code below works, but only returns the last product name. I know I'm sort of on the right track here, but I'm maxed out and cannot figure this out. Any help would be greatly, greatly appreciated. Thanks.
$names = array();
$result = $xpath->query("//div[#class='product-name']");
foreach ($result as $nam) {
$names[] = $nam->nodeValue;
$i = 0;
$values=$names[$i] = $nam->nodeValue;
}
$list = array (
array('Product Name','Stock Level','Price'),
array($values, '456', '789'),
);
$fp = fopen('product-sheet.csv', 'w');
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
I'm not entirely sure what you're trying to achieve but hopefully this will get you nearer to your goal.
<?php
//mocked up input, substitute for your HTML source
$input = "<html>
<div class='product-name'>test1</div>
<div class='product-name'>test2</div>
<div class='product-name'>test3</div>
<div class='product-name'>test4</div>
<div class='product-name'>test5</div>
</html>";
$doc = new DOMDocument();
#$doc->loadHTML($input);
libxml_use_internal_errors(FALSE);
$xpath = new DomXPath($doc);
$list = array (
array('Product Name','Stock Level','Price')
);
$result = $xpath->query("//div[#class='product-name']");
foreach ($result as $nam) {
$value = $nam->nodeValue;
$list[] = array($value, '456', '789'); //Appends an array to the lists array
}
$fp = fopen('product-sheet.csv', 'w');
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
?>
The problem is you're setting $i inside your loop.
foreach ($result as $nam) {
$names[] = $nam->nodeValue;
$i = 0;
$values=$names[$i] = $nam->nodeValue;
}
On each iteration, $i is being reset to 0. Try something like this instead:
for($i=0; $i< count($result); $i++) {
$names[] = $result->nodeValue;
$values=$names[$i] = $result->nodeValue;
}