sum column data in csv file using php - php

I have a php code that, based on a form, creates a csv file with 2 columns containing numbers (quantity and price) and a subtotal column that multiplies these two numbers.
I would like to be able to add up all the cells in the "subtotal" column to get the total.
I am a beginner in php.
Can you please help me?
Thank you very much!
My code :
<?php
$data_file = __DIR__ . '/data.csv';
$subtotal = $_POST['quantity']*$_POST['price'];
$total=[];
if (isset($_POST['quantity'])) { //
$stream = fopen($data_file, 'a');
fputcsv($stream, [$_POST['quantity'], $_POST['price'], $subtotal], ',', '"', ' ');
fclose($stream);
}
$stream = fopen($data_file, 'r');
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>document</title>
</head>
<body>
<table border="1">
<tr>
<th>Quantity</th>
<th>Price</th>
<th>Subtotal</th>
</tr>
<?php while ($record = fgetcsv($stream, 0, ',', '"', ' ')): ?>
<tr>
<td><?= htmlspecialchars($record[0]) ?></td>
<td><?= htmlspecialchars($record[1]) ?></td>
<td><?= htmlspecialchars($record[2]) ?></td>
</tr>
<?php endwhile ?>
</table>
<!-- The total should appear here, after the table-->
</body>
</html>
I tried to use the array_sum property and to browse the subtotal column but I could not solve my problem.

By utilising the while loop you already have, you can increment the subtotal on each iteration, and then display the total afterwards:
<table border="1">
<tr>
<th>Quantity</th>
<th>Price</th>
<th>Subtotal</th>
</tr>
<?php
$stream = fopen("file.csv", "r");
$subtotal_sum = 0;
while ($record = fgetcsv($stream, 0, ',', '"', ' ')): ?>
<tr>
<td><?= htmlspecialchars($record[0]) ?></td>
<td><?= htmlspecialchars($record[1]) ?></td>
<td><?= htmlspecialchars($record[2]) ?></td>
</tr>
<?php
$subtotal_sum += (float) $record[2];
endwhile;
fclose($stream);
$tax = $subtotal_sum * 0.1;
$total = $subtotal_sum + $tax;
?>
<tr>
<td colspan="2">Subtotal:</td>
<td><?=$subtotal_sum?></td>
</tr>
<tr>
<td colspan="2">Tax (10%):</td>
<td><?=$tax?></td>
</tr>
<tr>
<td colspan="2">Total:</td>
<td><?=$total?></td>
</tr>
</table>
This is a cool little one-liner that achieves the same subtotal summing but requires you to fetch the data from the file again:
echo array_reduce(array_map('str_getcsv', file('file.csv')), function($carry, $item) { return $carry + (int) $item[2]; }, 0);

Related

JQuery DataTables not displaying properly when populating table from MySql Table

The problem is all in my PHP WHILE Loop somehow, I know this for sure. It turns off all the DataTables features when I use this PHP script inside a table. All the sorts and pagination features are not present when I use "PHP WHILE" in conjuction with DataTables.
But if I type direct text in the "Example_Value" between TD tags it works fine.
It is pulling data from MySql Table and displaying correct value. Somehow the PHP script is turning off all the DataTables features.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="http://fonts.cdnfonts.com/css/lato" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap5.min.css">
<?php
$dir = '../customer/demo/';
$company_name_array = scandir($dir);
$company_count = count($company_name_array);
$i = 1;
// Loop through array
foreach($company_name_array as $stores){
$storesdisplay[$i] = $stores;
$i=$i+1;
}
require 'dbConfig2.php';
?>
<div class="container-fluid">
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Company</th>
<th>Phone</th>
<th>Contact</th>
<th>Email</th>
<th>Last Contact</th>
<th>Send</th>
</tr>
</thead>
<tbody>
<?php
$company_name = $company_name_array;
$i=1;
// Loop through array
while($i <= $company_count ){
$i=$i+1;
$company_name = $storesdisplay[$i];
$stmt = $conn->prepare("SELECT * FROM $company_name WHERE record_id =:record_id");
$stmt->bindValue(':record_id',1, PDO::PARAM_INT);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
?>
<tr>
<td><a href="<?php echo $dir.$company_name ?>/index.php?company_logo=<?php echo $row['company_logo'] ?>"><?php echo str_replace("_"," ",$company_name) ?></td>
<td><?php echo $row['phone'] ?></td>
<td><?php echo $row['contact'] ?></td>
<td><?php echo $row['email'] ?></td>
<td><?php echo $row['last_contact'] ?></td>
<td><button class="btn">Send</button></td>
</tr>
<?php
}
}
?>
</tbody>
<tfoot>
<tr>
<th>Company</th>
<th>Phone</th>
<th>Contact</th>
<th>Email</th>
<th>last_contact</th>
<th>Send</th>
</tr>
</tfoot>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.js" ></script>
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.11.5/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function() {
$('#example').DataTable();
} );
</script>
Thank you KIKO Software for leading me down the right path. In-fact you were correct, PHP was throwing an error. As I was loading $company_name into array, the first file read was "..". I corrected this problem with one simple correction. I initialized $i = 1; , rather than $i = 0;

For loop leaves blank td in a table

I am calling a for loop to get data from database with this code which is working fine but only with one problem
<table class="table" style="color:#000 !important;">
<tbody>
<tr>
<th>Question</th>
<th>User Answer</th>
</tr>
<tr>
</<?php
for ($x = 0; $x <= 30; $x++) {
?> <td><?= $info['ans_' . $x]; ?></td>
</tr>
<tr>
<?php
$sales_quiz = mysqli_query($conn_quiz, "SELECT * FROM `sales_quiz` where `que_no` = '$x'");
$sales_que = mysqli_fetch_array($sales_quiz); ?>
<td><?= $sales_que['que']; ?></td>
<?php }; ?>
</tr>
</tbody>
</table>
The result is first td of 2nd data which is que is blank and for loop start counting it from 2nd row
I do create a separate for loop for question and answer but then the table becomes broken.
If you need new rows in a table for every loop then you need to add the tr within the loop.
Also all tds that need to be on the same row has to be within one tr.
So remove the extra <tr> and bring them inside the loop.
<table class="table"
style="color:#000 !important;">
<tbody>
<tr>
<th>Question</th>
<th>User Answer</th>
</tr>
<?php
for ($x = 0; $x <= 30; $x++) {
?>
<tr>
<td><?= $info['ans_' . $x]; ?></td>
<!-- </tr> Remove these-->
<!-- <tr>-->
<?php
$sales_quiz = mysqli_query($conn_quiz, "SELECT * FROM `sales_quiz` where `que_no` = '$x'");
$sales_que = mysqli_fetch_array($sales_quiz);
?>
<td><?= $sales_que['que']; ?></td>
</tr>
<?php
} # the semi-colon (;) at the end is unnecessary
?>
</tbody>
</table>
You need to move your </tr><tr> to after the last td, and probably swap your $info['ans_'.$x]; and $sales_que['que']; since it seems like it should go question then answer, and the variable names make me think you are doing answer then question.
<table class="table" style="color:#000 !important;">
<tbody>
<tr>
<th>Question</th>
<th>User Answer</th>
</tr>
<tr>
<?php
for ($x = 0; $x <= 30; $x++) {
?> <td><?= $sales_que['que']; ?></td>
<?php
$sales_quiz = mysqli_query($conn_quiz, "SELECT * FROM `sales_quiz` where `que_no` = '$x'");
$sales_que = mysqli_fetch_array($sales_quiz); ?>
<td><?= $info['ans_'.$x]; ?></td>
</tr>
<tr>
<?php }; ?>
</tr>
</tbody>
</table>
I think it might be the "</" in the 10th line of your code, before the first <?php . There is any reason for that "</" to be there? From my perspective that creates a empty <tr></tr> on the resultant html file, and thats why you have that empty cell on your table. I might be wrong, just check it out and tell me if it works.

problem getting the right outcome with foreach

I have the following code to generate a HTML table with the placed orders.
// Select data FROM ORDER & ORDERLINE
$id = $value->ID;
$datenow = date("Y-m-d");
$temp = 0;
$stmt2 = $mysql->prepare("SELECT salesorder.order_id AS soid, salesorder.delivery_date AS sdd, orderline.qty AS olq, food.food_type AS fft
FROM orderline
INNER JOIN salesorder ON salesorder.order_id = orderline.order_id
INNER JOIN food ON food.food_id = orderline.food_id
WHERE salesorder.client_id=? AND orderline.qty!=?
ORDER BY sdd");
$stmt2->bind_param('ss', $id, $temp);
$stmt2->execute();
$result2 = $stmt2->get_result();
// determen if there are orders to display
if (mysqli_num_rows($result2) > 0) {
while ($value2 = $result2->fetch_object()) {
$results[] = $value2;
}
?>
<table class="center table">
<thead>
<tr>
<th>Order Number</th>
<th>Delivery Date</th>
<th>QTY</th>
<th>Food Type</th>
</tr>
</thead>
<tbody>
<b>Delivered orders :</b> (and orders delivered today...)
<?php foreach ( $results as $result ) : ?>
<?php if (($result->sdd)<=$datenow) { ?>
<td><?php echo ($result->soid); ?></td>
<td><?php echo ($result->sdd); ?></td>
<td><?php echo ($result->olq); ?></td>
<td><?php echo ($result->fft); ?></td>
</tr>
<?php } ?>
<?php endforeach;?>
</tbody>
</table>
The problem is that the 'delivery date' and 'order number' ALSO are displayed as many times as there are QTY and food types. i know this has to do with indexes, but however i try, i cant find the right syntax or way to do it. Any ideas?
I have added the data tables as images. Please let me know...
Inside of foreach u need to open <tr> Tag
You Can Loop the array directly mysqli_fetch_assoc returning array, then why you store into $results[] array,
Based on your comments on the other answer by Eibs please could you check if the following gives you what you need. First when you are looping the results we create an associative array grouped by the order number and date and add each item to the items array. Then when creating the table we loop the results array and then the items array. I have used separate rows only because you have a headings row, however, using this same approach you can design your table output a number of different ways.
// determen if there are orders to display
if(mysqli_num_rows($result2) > 0)
{
while($value2 = $result2->fetch_object())
{
$key = $value2->soid.'-'.$value2->sdd;
if(!isset($results[$key]))
{
$results[$key] = array(
'soid' => $value2->soid,
'sdd' => $value2->sdd,
'items' => array(),
);
}
$results[$key]['items'][] = $value2;
}
}
?>
<table class="center table">
<thead>
<tr>
<th>Order Number</th>
<th>Delivery Date</th>
<th>QTY</th>
<th>Food Type</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4"><b>Delivered orders :</b> (and orders delivered today...)</td>
</tr>
<?php foreach($results as $result) : ?>
<?php if($result['sdd'] <= $datenow): ?>
<tr>
<td><?php echo($result['soid']); ?></td>
<td><?php echo($result['sdd']); ?></td>
<td></td>
<td></td>
</tr>
<?php foreach($result['items'] as $item): ?>
<tr>
<td></td>
<td></td>
<td><?php echo($item->olq); ?></td>
<td><?php echo($item->fft); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
<?php endforeach; ?>
</tbody>
</table>

PHP HTML table retrieve multiple data in one <td> tag

I'm trying to generate a list from database in a HTML table just like image below;
https://i.stack.imgur.com/61XLl.png
And here's what i did;
https://i.stack.imgur.com/lLsvF.png
And the code;
<table cellpadding="3" border="1" style="width:100%;margin-top:30px; margin-bottom:50px; font-size:12px">
<thead>
<tr>
<th>KURSUS</th>
<th rowspan="2">NAMA PENSYARAH</th>
<th rowspan="2">NO. SIRI</th>
</tr>
<tr>
<th>NAMA</th>
</tr>
</thead>
<tbody align="center">
<?php
if($numrow>0)
{
while($row = $select->fetch_assoc()){
$code=explode("/",$row['po_code']);
$list=$connect->query("SELECT * FROM polist WHERE polist_poid='".$row['po_id']."' ORDER BY polist_bil ASC");
?>
<tr>
<td><?php echo $row['po_name']; ?></td>
<?php while($rowlist = $list->fetch_assoc()){
$name=$connect->query("SELECT * FROM user WHERE user_id='".$rowlist['polist_userid']."'");
$rowname=$name->fetch_array();?>
<td><?php echo $rowname['user_name']; ?></td>
<td><?php echo $code[0]."/PO/".$code[1]." - ".$rowlist['polist_bil']; ?></td>
<?php } ?>
</tr>
<?php
}
}
?>
</tbody>
</table>
Help me. Thank you in advance :)
Use this code. Concat user names and code with "br" tags in the second while loop and display them in "tds" after while loop.
<tbody align="center">
<?php
if($numrow>0)
{
while($row = $select->fetch_assoc()){
$code=explode("/",$row['po_code']);
$list=$connect->query("SELECT * FROM polist WHERE polist_poid='".$row['po_id']."' ORDER BY polist_bil ASC");
?>
<tr>
<td><?php echo $row['po_name']; ?></td>
<?php
$user_names = $codes = ''; // define empty variables
while($rowlist = $list->fetch_assoc()){
$name=$connect->query("SELECT * FROM user WHERE user_id='".$rowlist['polist_userid']."'");
$rowname=$name->fetch_array();
$user_names .= $rowname['user_name']."<br/>"; //concat to a single string
$codes .= $code[0]."/PO/".$code[1]." - ".$rowlist['polist_bil']."<br/>"; //concat to a single string
}?>
<td><?php echo $user_names;?></td>
<td><?php echo $codes;?></td>
</tr>
<?php
}
}
?>
</tbody>
Put the <td> outside the <?php while($rowlist = $list->fetch_assoc()){
Or get all your data before you start display html and store it in a multi-dimensional array. Then simply loop through the data array. That way you won't have as much php mixed with html also.

how can i echo contents of 2 associative arrays into one table?

this is my code snippets and the result is not the thing that i want.I have 2 associative arrays and want to echo their contents into one table like before the html tag.how can i do that?
team A: team B:
player_one player_five
player_two player_six
player_three player_seven
player_four player_eight
<html>
<head>
<title>Untitled</title>
</head>
<body>
<table widht='100%' border="1">
<tr>
<td>team A</td>
<td>team B</td>
</tr>
<?php
$team_a=array("goalkeeper"=>"player_one","defender"=>"player_two","midfielder"=>"player_three","forward"=>"player_four");
$team_b=array("goalkeeper"=>"player_five","defender"=>"player_six","midfielder"=>"player_seven","forward"=>"player_eight");
foreach($team_a as $index1 => $value1 ){
foreach($team_b as $index2 => $value2 )
echo "
<tr>
<td>$value1</td>
<td>$value2</td>
</tr>
";
}
?>
</table>
</body>
</html>
// drop indexes because you don't use them anyway
$a = array_values($team_a);
$b = array_values($team_b);
// process arrays
max = max(count($a), count($b));
for ($i=0; $i < $max; $i++) {
echo '
<tr>
<td>' . (isset($a[$i] ? $a[$i] : '-')) . '</td>
<td>' . (isset($b[$i] ? $b[$i] : '-')) . '</td>
</tr>
';
}
Alternatively, you could combine the arrays first and line them up accordingly, them print them:
<?php
$team_a=array("goalkeeper"=>"player_one","defender"=>"player_two","midfielder"=>"player_three","forward"=>"player_four");
$team_b=array("goalkeeper"=>"player_five","defender"=>"player_six","midfielder"=>"player_seven","forward"=>"player_eight");
$teams = array();
$keys = array_keys($team_a);
foreach ($keys as $key) {
$teams[$key] = array($team_a[$key], $team_b[$key]);
}
?>
<table widht='100%' border="1">
<tr>
<td>team A</td>
<td>team B</td>
</tr>
<?php foreach($teams as $players): ?>
<tr>
<?php foreach($players as $player): ?><td><?php echo $player; ?></td><?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
Output
Or if you do not want the original arrays touched or using a new array, then just loop them accordingly:
<?php
$team_a=array("goalkeeper"=>"player_one","defender"=>"player_two","midfielder"=>"player_three","forward"=>"player_four");
$team_b=array("goalkeeper"=>"player_five","defender"=>"player_six","midfielder"=>"player_seven","forward"=>"player_eight");
?>
<table widht='100%' border="1">
<tr>
<td>team A</td>
<td>team B</td>
</tr>
<?php foreach($team_a as $key => $value): ?>
<tr>
<td><?php echo $value; ?></td><td><?php echo $team_b[$key]; ?></td>
</tr>
<?php endforeach; ?>
</table>

Categories