Take HTML Output and insert it Excel Document via PHPExcel? - php

I already have my desired data retrieved from the database and output it via the browser for web use but now I am trying to insert it in to an excel doc and email it.
I have the beginnings of the document and am able to email it as an attachment fine, it's just how to transpose the html output into the excel document that I am stuck at as I can't think of the best way to do it.
This is how I achieve my HTML output (apologies for the length):
// print table
echo '<table>';
echo '<tr><th rowspan="2">Day</th>';
foreach($typesorder as $type) {
if(in_array($type, $types)) {
echo '<th colspan="3">' . $type . '</th>';
}
}
echo '<th colspan="3">Total Conversions</th>';
echo '</tr>';
echo '<tr>';
foreach($typesorder as $type) {
if(in_array($type, $types)) {
echo '<th>Week ' . $weekstart_A_data['week'] . ' ' . $weekstart_A_data['year'] . '</th>';
echo '<th>Week ' . $weekstart_B_data['week'] . ' ' . $weekstart_B_data['year'] . '</th>';
echo '<th>+/-</th>';
}
}
// Total Conversions section
echo '<th>Week ' . $weekstart_A_data['week'] . ' ' . $weekstart_A_data['year'] . '</th>';
echo '<th>Week ' . $weekstart_B_data['week'] . ' ' . $weekstart_B_data['year'] . '</th>';
echo '<th>+/-</th>';
echo '</tr>';
foreach($dailytotals as $thedate => $data) {
$daily_conversions = 0;
$daily_conversionsB = 0;
echo '<tr>';
echo '<td>' . date('l', strtotime($thedate)) . '</td>';
foreach($typesorder as $type) {
if(in_array($type, $types)) {
$conversions = $data[$type];
$total_conversions[$type] += $conversions;
$daily_conversions += $conversions;
$week_A_conversions = $conversions;
$week_B_conversions = $dailytotalsB[$weekstartB][$type];
$total_conversionsB[$type] += $dailytotalsB[$weekstartB][$type];
$daily_conversionsB += $week_B_conversions;
$differential = $dailytotalsB[$weekstartB][$type] - $conversions;
echo '<td>'. number_format($week_A_conversions) . '</td>';
echo '<td>'. number_format($week_B_conversions) . '</td>';
if($differential < 0 ) {
$class = "class='diffred'";
} else if($differential > 0) {
$class = "class='diffblue'";
} else {
$class='';
}
// differential between Week A and Week B
echo '<td ' . $class . '>' . $differential . '</td>';
}
}
$weekstartB = date("Y-m-d", strtotime('+1 day', strtotime($weekstartB)));
$differentialtotal = $daily_conversionsB - $daily_conversions;
echo '<td>' . number_format($daily_conversions) . '</td>';
echo '<td>' . number_format($daily_conversionsB) . '</td>';
if($differentialtotal < 0 ) {
$class = "class='diffred'";
} else if($differentialtotal > 0) {
$class = "class='diffblue'";
} else {
$class='';
}
echo '<td ' . $class . '>' . $differentialtotal . '</td>';
echo '</tr>';
}
echo '<tr>';
echo '<td><strong>Total</strong></td>';
// reset both week A and B
$overall_conversions = 0;
$overall_conversionsB = 0;
foreach($typesorder as $type) {
if(in_array($type, $types)) {
$conversions = $total_conversions[$type];
$overall_conversions += $conversions;
$conversionsB = $total_conversionsB[$type];
$overall_conversionsB += $conversionsB;
echo '<th>' . number_format($conversions) . '</th>';
echo '<th>' . number_format($conversionsB) . '</th>';
echo '<th>' . number_format($conversionsB - $conversions) . '</th>';
}
}
echo '<th>' . number_format($overall_conversions) . '</th>';
echo '<th>' . number_format($overall_conversionsB) . '</th>';
echo '<th>' . number_format($overall_conversionsB - $overall_conversions) . '</th>';
echo '</tr>';
echo '</table>';
This outputs a table with the following structure:
----------------------------------------------------------------------------------
| | Type 1 | Type 2 | ... | Total Conversions |
| Day -------------------------------------------------------------------------|
| | Week 1 2013 | Week 1 2012 | ... | ... | ... | ... | ... |
|--------------------------------------------------------------------------------|
|Sunday | 135 | 143 | ... | ... | ... | ... | ... |
|--------------------------------------------------------------------------------|
| ... | ... | ... | ... | ... | ... | ... | ... |
|--------------------------------------------------------------------------------|
|Total | ... | ... | ... | ... | ... | ... | ... |
----------------------------------------------------------------------------------
Hopefully that makes some sense, the ... are just placeholders for repeating data.
I don't need to do any formulas since I already have all the data I need but I wouldn't rule it out as it might be easier to total using PHPExcel.
I know this is a horrible question but I am genuinely stumped how to start off. I'm not expecting the full, exact answer to my specific scenario (although that would be magical) but in reality any pointers would help.
P.S. I know how to insert data into the Excel document using PHPExcel but it's transposing my table that's the problem. I think the first step is to add all the data to a multi-dimensional array instead of printing it but I will see what the responses are first.
Also, please note that I don't want to output as CSV as I wish to automatically email the pre-prepared and formatted Excel sheet.

Related

How to customize pagination in laravel to show a number of elements for each page

my application basically generate reports for some users
I fetch the rows from the database
every row contains a 'name' and 'work time' and others...
every user has multiple rows with the same name but a different work time value
I calculated the total of the 'work time' in the blade depending on the next row if its the same name I 'll keep adding work time, if the next row is for another user then I will show the total for the current user and start calculating the total for the next user
my problem is with pagination:
at the end of each page, the rows of the same user do not appear all of it
and my blade logic calculate only what appears on that page (see the picture)
notice here that other rows with the same name exist in the second page
and their total calculated separately
is there is any way to tell the paginator to devise rows on a condition besides that number ->paginate(15+condition) because I want all the rows for a specific user to stay on the same page.
this is the query:
$shifts = DB::table('driver_shifts')
->join('drivers','drivers.PermitNumber','=','driver_shifts.driver_badge_id')
->where ('driver_shifts.shift_start_time','>',$startDate)
->where ('driver_shifts.shift_start_time','<',$endDate)
->orderby('drivers.LastName')
->orderby('driver_shifts.shift_start_time')
->paginate(20)
->appends(request()->query());
this is the blade logic inside a table. Ps: I know it not a good practice but I coudn't find a better way to do it in the controller:
$total_time = 0.00;
$break_time = 0.00;
$work_time = 0.00;
for ($i = 0; $i < count($shifts); $i++)
{
$break_time_item = $shifts[$i]->total_time - $shifts[$i]->work_time;
echo '<tr>';
echo '<td>' . $shifts[$i]->FirstName . ' ' . $shifts[$i]->LastName . '</td>';
echo '<td>' . $shifts[$i]->vehicle_id . '</td>';
echo '<td>' . $shifts[$i]->shift_start_time . '</td>';
echo '<td>' . $shifts[$i]->shift_end_time . '</td>';
echo '<td>' . $shifts[$i]->total_time . '</td>';
echo '<td>' . $break_time_item . '</td>';
echo '<td>' . $shifts[$i]->work_time . '</td>';
echo '</tr>';
//calculation totals for the current driver
//dd($shifts[$i]->break_time);
$total_time = $total_time + $shifts[$i]->total_time;
$work_time = $work_time + $shifts[$i]->work_time;
if (isset($shifts[$i + 1]))
{
if ($shifts[$i]->LastName !== $shifts[$i + 1]->LastName)
{
//calculating break time
$break_time = $total_time - $work_time;
//converting minutes to houres
$total_time_hours = floor($total_time / 60);
$total_time_min = $total_time - ($total_time_hours * 60);
$work_time_hours = floor($work_time / 60);
$work_time_min = $work_time - ($work_time_hours * 60);
$break_time_hours = floor($break_time / 60);
$break_time_min = $break_time - ($break_time_hours * 60);
echo '<tr class="table-primary text-uppercase ">';
echo '<td colspan="4">' . $shifts[$i]->FirstName . ' ' . $shifts[$i]->LastName . ' TOTAL ' . '</td>';
if ($total_time_hours == 0 && $total_time_min == 0)
{
echo '<td>-</td>';
}
else
{
echo '<td>' . $total_time_hours . "h:" . $total_time_min . "min" . '</td>';
}
if ($break_time_hours == 0 && $break_time_min == 0)
{
echo '<td>-</td>';
}
else
{
echo '<td>' . $break_time_hours . "h:" . $break_time_min . "min" . '</td>';
}
if ($work_time_hours == 0 && $work_time_min == 0)
{
echo '<td>-</td>';
}
else
{
echo '<td>' . $work_time_hours . "h:" . $work_time_min . "min" . '</td>';
}
echo '</tr>';
$total_time = 0;
$break_time = 0;
$work_time = 0;
}
}

PHP - json - function call issue

I am having two functions printBefore(json1) and printAfter(json2).
Both are having json object as parameter.jsons are coming from database. They are parsing json and displaying it in correct format.
But it is taking more than 30 seconds.
When I removed functon and displays json as it is. It is not taking time more than second.
I am not able isolate problem. Please Help.
foreach ($records as $record) {
echo '<tr>';
echo '<td>' . $userNames['users'][$record->uid] . '</td>';
echo '<td>' . $userNames['users'][$record->uid] . '</td>';
echo '<td>' . $record->val . '</td>';
echo '<td>' . $record->mi. '</td>';
echo '<td>' . $record->created_on . '</td>';
echo '<td>' . printBefore($record->newData) . '</td>';
echo '<td>' . printAfter($record->oldData) . '</td>';
echo '</tr>';
}
Code for printAfter($oldData)
$oldData = json_decode($oldData, true);
if (isset($OldData['sub_category'])) {
$str = $str . "|Category : " . $this->category[$OldData['sub_category']] . "|";
}
code for PrintBefore($newData)
$newData = json_decode($newData, true);
if (isset($newData['sub_category'])) {
$str = $str . "|Category : " . $this->category[$newData['sub_category']] . "|";
}

Codeigniter Pagination: How to properly do results numbering

How can I properly do the the numbering of the results? What i did was
<?php
if($results)
{
$x = 1;
foreach ($results as $data)
{
echo '<tr>';
echo '<td>' . $x++. '</td>';
echo '<td>' . $data->item_id . '</td>';
echo '<td>' . $data->item_name . '</td>';
echo '<td>' . $data->item_category . '</td>';
echo '<td>' . $data->item_costprice . '</td>';
echo '<td>' . $data->item_retailprice . '</td>';
echo '<td>' . $data->item_tax . '%</td>';
echo '</tr>';
}
}
?>
But it has the same numbering per page.
The numbering starts with 1 because thats the value you assign to it before the loop starts.
Assuming you pass the page number to your controller your could do the following:
$x = count($results) * ($pagenumber-1);//use count or some other type of count method
This will make the $x value 1 on the first page, 31 on the second page, 61 on the third page etc...
Then inside the loop change $x++ to ++$x otherwise the first page will be counted from 0 to 29.

How to create dynamic matrix in php?

I have this table "city" in my database:
|id |id_city_a |id_city_b|distance|
|1 |1 | 1 | 0 |
|2 |1 | 2 | 8 |
|3 |1 | 3 | 6 |
|4 |2 | 1 | 8 |
|5 |2 | 2 | 0 |
|6 |2 | 3 | 9 |
|7 |3 | 1 | 6 |
|8 |3 | 2 | 9 |
|9 |3 | 3 | 0 |
I want the end result to be in a matrix, such as:
| | 1 | 2 | 3 |
| 1 | 0 | 8 | 6 |
| 2 | 8 | 0 | 9 |
| 3 | 6 | 9 | 0 |
This is my code :
function random()
{
include('config/koneksi.php');
$result = mysql_query("select * from temp_hasil");
$n =mysql_num_rows(mysql_query("SELECT * FROM temp_hasil"));
for ($i = 1; $i <= $n; $i++)
{
for ($j = 1; $j <= $n; $j++)
{
$rows = mysql_fetch_array($result);
$this->table[$i][$j] = $i == $j ? INF : $rows['id'];
}
}
}
function __toString()
{
$str = '<table class="table table-bordered" id="tableInput"> <tbody>';
$str .= '<tr><td></td>';
foreach ($this->table as $rowName => $row)
{
$str .= "<td>$rowName</td>";
}
$str .= '</tr>';
foreach ($this->table as $rowName => $row)
{
$str .= "<tr><td>$rowName</td>";
foreach ($row as $columnName => $value)
{
$str .= "<td>";
$str .=
'<input class="form-control" type="text" value="' . $value . '" name="table[' . $rowName . '][' .
$columnName . ']" requied' . ($columnName == $rowName ? ' disabled' : '') . '>';
$str .= "</td>";
}
$str .= '</tr>';
}
$str .= '</tbody></table>';
return $str;
}
}
$str .= '</tr>';
foreach ($this->table as $rowName => $row)
{
$str .= "<tr><td>$rowName</td>";
foreach ($row as $columnName => $value)
{
$str .= "<td>";
$str .=
'<input class="form-control" type="text" value="' . $value . '" name="table[' . $rowName . '][' .
$columnName . ']" requied' . ($columnName == $rowName ? ' disabled' : '') . '>';
$str .= "</td>";
}
$str .= '</tr>';
}
$str .= '</tbody></table>';
return $str;
}
`
How do I code it in php? please help me.
Make city_a index completely different from city_b index so it is easy to check.
// generate a two-dimensional matrix in here
$distMatrix = array();
foreach($tableRows as $cityDist) {
$from = $cityDist['id_city_a'];
$to = $cityDist['id_city_b'];
$dist = $cityDist['distance'];
$distMatrix[$from][$to] = $dist;
}
Display as an HTML Table...
echo '<table border="1">';
echo '<tr>';
echo '<td>', '#', '</td>';
foreach(array_keys(current($distMatrix)) as $city_b) { // city_b headings
echo '<td>', $city_b ,'</td>';
}
echo '</tr>';
foreach(array_keys($distMatrix) as $city_a) { // need the city_a as row index
echo '<tr>';
echo '<td>', $city_a, '</td>'; // city_a ad
foreach(array_keys($distMatrix[$city_a]) as $city_b) { // need the city_b as column index
echo '<td>', $distMatrix[$city_a][$city_b], '</td>'; // distance from the matrix;
}
echo '</tr>';
}
echo '</table>';
Test data - used data from #ashkufaraz
// changed the city ids so we can easily see city_a and city_b
$tableRows[0]=array("id"=>1, "id_city_a"=>1, "id_city_b"=>11, "distance"=>0);
$tableRows[1]=array("id"=>2, "id_city_a"=>1, "id_city_b"=>12, "distance"=>8);
$tableRows[2]=array("id"=>3, "id_city_a"=>1, "id_city_b"=>13, "distance"=>6);
$tableRows[3]=array("id"=>4, "id_city_a"=>2, "id_city_b"=>11, "distance"=>8);
$tableRows[4]=array("id"=>5, "id_city_a"=>2, "id_city_b"=>12, "distance"=>0);
$tableRows[5]=array("id"=>6, "id_city_a"=>2, "id_city_b"=>13, "distance"=>9);
$tableRows[6]=array("id"=>7, "id_city_a"=>3, "id_city_b"=>11, "distance"=>6);
$tableRows[7]=array("id"=>8, "id_city_a"=>3, "id_city_b"=>12, "distance"=>9);
$tableRows[8]=array("id"=>9, "id_city_a"=>3, "id_city_b"=>13, "distance"=>0);
Output:
# 11 12 13
1 0 8 6
2 8 0 9
3 6 9 0
try like this
Online Demo
$tableRows[0]=array("id"=>1,"id_city_a"=>1,"id_city_b"=>1,"distance"=>0);
$tableRows[1]=array("id"=>2,"id_city_a"=>1,"id_city_b"=>2,"distance"=>8);
$tableRows[2]=array("id"=>3,"id_city_a"=>1,"id_city_b"=>3,"distance"=>6);
$tableRows[3]=array("id"=>4,"id_city_a"=>2,"id_city_b"=>1,"distance"=>8);
$tableRows[4]=array("id"=>5,"id_city_a"=>2,"id_city_b"=>2,"distance"=>0);
$tableRows[5]=array("id"=>6,"id_city_a"=>2,"id_city_b"=>3,"distance"=>9);
$tableRows[6]=array("id"=>7,"id_city_a"=>3,"id_city_b"=>1,"distance"=>6);
$tableRows[7]=array("id"=>8,"id_city_a"=>3,"id_city_b"=>2,"distance"=>9);
$tableRows[8]=array("id"=>9,"id_city_a"=>3,"id_city_b"=>3,"distance"=>0);
$counter=0;
$result=array();
foreach($tableRows as $tableRow)
{
$result[$tableRow["id_city_a"]][$tableRow["id_city_b"]]=array("id_city_a"=>$tableRow["id_city_a"],"id_city_b"=>$tableRow["id_city_b"],"distance"=>$tableRow["distance"] );
}
now in $result[cityA][cityB]=distance
get unique_id_city_a for column
$unique_id_city_a = array_unique(array_map(function ($i) { return $i['id_city_a']; }, $tableRows));
echo "\t";
foreach($unique_id_city_a as $R)
{
echo $R."\t";
}
echo "\n";
get unique_id_city_b for rows
$unique_id_city_b = array_unique(array_map(function ($i) { return $i['id_city_b']; }, $tableRows));
foreach($result as $R1)
{
echo $unique_id_city_b[$counter++]."\t";
foreach($R1 as $R2)
{
echo $R2["distance"]."\t";
}
echo "\n";
}

Prevent one data to loop

<?php
include ("config.php");
$results = $mysqli->query
("
SELECT orders_history.transaction_id,
orders_history.items,
orders_history.quantity,
orders_history.one_product_price,
orders_list.status,
orders_list.invoices,
orders_list.payment_method,
orders_list.order_method,
delivery_orders.address,
delivery_orders.service,
delivery_orders.cost,
delivery_orders.city
FROM orders_history
LEFT JOIN orders_list
ON orders_history.transaction_id = orders_list.transaction_id
LEFT JOIN infistall_order
ON orders_history.transaction_id = infistall_order.transaction_id
LEFT JOIN delivery_orders
ON orders_history.transaction_id = delivery_orders.transaction_id
WHERE orders_list.customer_name = 'Klaudia'"
);
$orders = array();
$html = '';
if ($results) {
while($obj = $results->fetch_object()) {
$orders[$obj->transaction_id][$obj->items] = array(
'invoices' => $obj->invoices,
'status' => $obj->status,
'payment_method' => $obj->payment_method,
'service' => $obj->service,
'cost' => $obj->cost,
'quantity' => $obj->quantity,
'one_product_price' => $obj->one_product_price,
'city' => $obj->city);
}
$html .= '<table width="70%"><tr>';
$html .= '<td>transaction_id</td>';
$html .= '<td>items</td>';
$html .= '<td>quantity</td>';
$html .= '<td>one_product_price</td>';
$html .= '<td>status</td>';
foreach ($orders AS $order_id => $order) {
$html .= '<tbody><tr><td rowspan="' . count($order) . '">' . $order_id . '</td>';
$row = 1;
foreach ($order AS $item => $data) {
if ($row > 1) { $html .= '</tr><tr>'; }
$html .= '<td>' . $item . '</td>';
$html .= '<td>' . $data['quantity'] . '</td>';
$html .= '<td>' . $data['one_product_price'] . '</td>';
$row++;
$html .= '<td rowspan="' . count($order) . '">' . $data['status'] . '</td>';
}
$html .= '</tr><tbody>';
}
$html .= '</table>';
}
echo $html;
?>
The code above will result like this:
-----------------------------------------------------------------------
id_cart products quantity invoices status
-----------------------------------------------------------------------
this 2 $20
-------------------------------------------------------
0001 that 1 $20 pending
-------------------------------------------------------
those 2 $20 pending pending
-----------------------------------------------------------------------
Total Invoices: $60
-----------------------------------------------------------------------
this 2 $20
-------------------------------------------------------
0002 that 1 $20 approved
-------------------------------------------------------
those 2 $20 approved approved
-----------------------------------------------------------------------
Total Invoices: $60
Have a look at the column of status, where the result is looping.
What I want is it shouldn't be looping and only get one result as how the column of id_cart looks like. This is the code for the column of status
$html .= '<td rowspan="' . count($order) . '">' . $data['status'] . '</td>';
I need to solve it!
[EDIT]
When I move the code like this:
foreach ($orders AS $order_id => $order) {
$html .= '<tbody><tr><td rowspan="' . count($order) . '">' . $order_id . '</td>';
$row = 1;
foreach ($order AS $item => $data) {
if ($row > 1) { $html .= '</tr><tr>'; }
$html .= '<td>' . $item . '</td>';
$html .= '<td>' . $data['quantity'] . '</td>';
$html .= '<td>' . $data['one_product_price'] . '</td>';
$row++;
}
$html .= '<td rowspan="' . count($order) . '">' . $data['status'] . '</td>';
$html .= '</tr><tbody>';
-----------------------------------------------------------------------
id_cart products quantity invoices status
-----------------------------------------------------------------------
this 2 $20
-------------------------------------------------------
0001 that 1 $20
-------------------------------------------------------
those 2 $20 pending
-----------------------------------------------------------------------
Total Invoices: $60
-----------------------------------------------------------------------
this 2 $20
-------------------------------------------------------
0002 that 1 $20
-------------------------------------------------------
those 2 $20 approved
-----------------------------------------------------------------------
Total Invoices: $60
The resultin the column of status in at the very bottom of the tbody. I want it as how the column of id_cart is.
You need 1 value of status per tbody, so put it outside your loop. Also, because you're reusing $order, I've put count($order) in a seperate variable. Also, close your </tbody> tag.
foreach ($orders AS $order_id => $order) {
$orderCount = count($order);
$html .= '<tbody><tr><td rowspan="' . $orderCount . '">' . $order_id . '</td>';
$row = 1;
foreach ($order AS $item => $data) {
if ($row > 1) { $html .= '</tr><tr>'; }
$html .= '<td>' . $item . '</td>';
$html .= '<td>' . $data['quantity'] . '</td>';
$html .= '<td>' . $data['one_product_price'] . '</td>';
if ($row == 1)
$html .= '<td rowspan="' . $orderCount . '">' . $data['status'] . '</td>';
$row++;
}
$html .= '</tr></tbody>';
}
Use valign attribute for td element to get the value aligned center vertically.
$html .= '<td rowspan="' . $orderCount . '" valign="middle">' . $data['status'] . '</td>';
Hope it will work for you.
Check this out:
foreach ($order AS $item => $data) {
if ($row > 1) { $html .= '</tr><tr>'; }
$html .= '<td>' . $item . '</td>';
$html .= '<td>' . $data['quantity'] . '</td>';
$html .= '<td>' . $data['one_product_price'] . '</td>';
if( $row == 1 )
{
$html .= '<td style="vertical-align: middle" rowspan="' . count($order) . '">'. $data['status'] . '</td>';
}
$row++;
}

Categories