Reputation: 319
I am looking to have a table built using php but with a twist. I want to only limit it to 10 rows. If the variable is greater than 10, then a new column is added. IE:
If the variable is 9 then the table will have 1 column and 9 rows. If the number is 19 then the table will contain 10 rows and 2 columns with the second columns containing numbers 11 - 19. And so on Similar to below
+----+-------+-------+----+-------+-------+----+-------+-------+
| Q | Tally | Total | Q | Tally | Total | Q | Tally | Total |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 1 | | | 11 | | | 21 | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 2 | | | 12 | | | 22 | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 3 | | | 13 | | | 23 | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 4 | | | 14 | | | 24 | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 5 | | | 15 | | | 25 | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 6 | | | 16 | | | | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 7 | | | 17 | | | | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 8 | | | 18 | | | | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 9 | | | 19 | | | | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
| 10 | | | 20 | | | | | |
+----+-------+-------+----+-------+-------+----+-------+-------+
Any idea how I can achieve this?
I have gotten this far
$table_string = 'Table Name 1:45,Table Name 2:20,Table Name 3:9';
function foo()
{
$tables = explode(',', $table_string);
$output = '';
foreach ($tables as $table)
{
$table_name = explode(':', $table)[0];
$table_rows = explode(':',$table)[1];
$table_columns = ceil($table_rows/10);
$output .= "<br>
<table class='table table-bordered table-small'>
<tr>
<th scope='col' colspan='99'>{$table_name}</th>
</tr>";
for ($x = 1; $x <=10; $x++)
{
$output .= "<tr>";
for ($y = 1; $y <= $table_columns * 3; $y++)
{
if ($y % 3 == 1) {
$output .= "<td scope=\"col\">Q</td>";
} else if ($y % 3 == 2) {
$output .= "<td scope=\"col\">Tally</td>";
} else {
$output .= "<td scope=\"col\">Total</td>";
}
}
$output .= "</tr>";
$output .= "<tr>";
for ($y = 1; $y <= $table_columns * 3; $y++)
{
if ($y == 1 || $y % 4 == 0) {
$z = ceil($y / 4);
$output .= "<td scope=\"row\">{$z}</td>";
} else {
$output .= "<td></td>";
}
}
$output .= "</tr>";
}
$output .= "</table>";
}
return $output;
}
To help answer the question more: Here is the current output I get:
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| Q | Tally | Total | Q | Tally | Total | Q | Tally | Total | Q | Tally | Total | Q | Tally | Total |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
| 1 | | | 1 | | | | 2 | | | | 3 | | | |
+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+---+-------+-------+
Upvotes: 2
Views: 2344
Reputation: 10081
You can try the following code:
<?php
// -------- Functions --------
function foo($tables_string)
{
// Decompose tables string
$tables = explode(',', $tables_string);
// Header of the 3 columns
$headers = "<td class='bg_gray' scope='col'>Q</td>"
. "<td class='bg_gray' scope='col'>Tally</td>"
. "<td class='bg_gray' scope='col'>Total</td>";
// Starts output empty
$output = "";
// For each table string
foreach ($tables as $table)
{
// Use of list() to store explode in multiple variables
list($table_name, $table_rows) = explode(':', $table);
// Calculate number of columns
$table_columns = ceil($table_rows/10);
// Starts table
$output .= "<br>
<table class='table table-bordered table-small'>
<tr>
<th scope='col' colspan='99'>{$table_name}</th>
</tr>";
// Use str_repeat() instead of a loop
$output .= "<tr>".str_repeat($headers, $table_columns)."</tr>";
// Loop for trs
for ($x = 1; $x <= 10; $x++)
{
$output .= "<tr>";
// Loop for tds
for ($y = 0; $y < $table_columns * 3; $y++)
{
//z = number of the “row”
$z = (10 * $y / 3) + $x;
// If first column, and not end of our data
if(($y % 3 == 0) && ($z <= $table_rows)){
$output .= "<td scope='row'>{$z}</td>";
} else {
$output .= "<td> </td>";
}
}
// End of table row
$output .= "</tr>";
}
// End of table
$output .= "</table>";
}
return $output;
}
// -------- Main script --------
// Stylize the output
echo "<style>
table { border-collapse: collapse; }
td { padding: 4px 8px; border: 1px solid gray; }
.bg_gray { background: lightgray; }
</style>";
// Use the function above
$tables = 'Table Name 1:45,Table Name 2:20,Table Name 3:9';
echo foo($tables);
?>
… in which I did the following:
Some of the functions I used to simplify:
⋅ ⋅ ⋅
Upvotes: 0
Reputation: 789
Forgive me if I over complicated things, but I tried to approach this a little bit different :)
interface DrawableTable
{
public function draw ();
}
class Table implements DrawableTable
{
const MAX_ALLOWED_ROWS = 10;
protected $name;
protected $rows;
protected $cols;
/**
* @var TableHeaderContract $header
*/
protected $header;
/**
* @var TableBodyContract $body
*/
protected $body;
public function __construct ($name, $rows, $cols)
{
$this->name = $name;
$this->rows = $rows;
$this->cols = $cols;
$this->header = new TableHeader(ceil($this->cols / self::MAX_ALLOWED_ROWS), ['Q', 'Tally', 'Total']);
$this->body = new TableBody(self::MAX_ALLOWED_ROWS);
//Here I am adding random numbers but you can call body and add as you need them!
for ($randI = 1; $randI <= $this->cols; $randI++) {
$this->body->addRow(new Row($randI, '', ''));
}
}
public function draw ()
{
return (new TableMarshaller)($this);
}
/**
* @return mixed
*/
public function getName ()
{
return $this->name;
}
/**
* @return mixed
*/
public function getRows ()
{
return $this->rows;
}
/**
* @return mixed
*/
public function getCols ()
{
return $this->cols;
}
/**
* @return TableHeaderContract
*/
public function getHeader ()
{
return $this->header;
}
/**
* @return TableBodyContract
*/
public function getBody ()
{
return $this->body;
}
}
interface TableHeaderContract
{
public function drawHeaders ();
}
class TableHeader implements TableHeaderContract
{
protected $repetitions;
protected $headers = [];
public function __construct ($repetitions, $headers = [])
{
$this->repetitions = $repetitions;
$this->addHeadersAccordingToRows($headers);
}
private function addHeadersAccordingToRows ($headers)
{
for ($iteration = 0; $iteration < $this->repetitions; $iteration++) {
$this->headers = array_merge($this->headers, $headers);
}
}
/**
* @return array
*/
public function getHeaders ()
{
return $this->headers;
}
public function drawHeaders ()
{
return (new HeaderThreeMarshaller)($this);
}
}
class Row
{
protected $id;
protected $tally;
protected $total;
public function __construct ($id, $tally, $total)
{
$this->id = $id;
$this->tally = $tally;
$this->total = $total;
}
/**
* @return mixed
*/
public function getId ()
{
return $this->id;
}
/**
* @param mixed $id
*
* @return Row
*/
public function setId ($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getTally ()
{
return $this->tally;
}
/**
* @param mixed $tally
*
* @return Row
*/
public function setTally ($tally)
{
$this->tally = $tally;
return $this;
}
/**
* @return mixed
*/
public function getTotal ()
{
return $this->total;
}
/**
* @param mixed $total
*
* @return Row
*/
public function setTotal ($total)
{
$this->total = $total;
return $this;
}
}
interface TableBodyContract
{
public function drawBody ();
}
class TableBody implements TableBodyContract
{
protected $allowedRowSize;
/**
* @var array $rows Multi Dimentional array!
*/
protected $rows = [];
public function __construct ($maxRowSize)
{
$this->allowedRowSize = $maxRowSize;
}
public function addRow (Row $row)
{
//$this->rows[(int)(floor($row->getId() % 10))][] = $row;
//Makes sure to instanciate all allowed rows
if (count($this->rows) < $this->allowedRowSize) {
$this->rows[count($this->rows)][] = $row;
return $this;
}
for ($i = 0; $i < count($this->rows); $i++) {
if (array_key_exists($i + 1, $this->rows)) {
// if current have euqal or less values than the next, means we need to add it here!
if (count($this->rows[$i]) < count($this->rows[($i + 1)])) {
$this->rows[$i][] = $row;
return $this;
} else if (count($this->rows[$i]) <= count($this->rows[count($this->rows) - 1])) {
$this->rows[$i][] = $row;
return $this;
}
continue;
}
}
$this->rows[count($this->rows) - 1][] = $row;
return $this;
}
/**
* @return array
*/
public function getRows ()
{
return $this->rows;
}
public function drawBody ()
{
return (new BodyMarshaller)($this);
}
}
/**
* MARSHALLERS TO PARSE TO YOUR VIEW
*/
class TableMarshaller
{
/**
* @var Table $table
*/
protected $table;
protected $htmlOutput;
public function __invoke (Table $table)
{
$this->table = $table;
//Wrap table into a div
$this->htmlOutput = '<div>';
//Table -> Name
$this->attachTableName();
//Table -> Header and Body
$this->attachTableContent();
$this->htmlOutput .= '</div>';
return $this->htmlOutput;
}
private function attachTableName ()
{
$this->htmlOutput .= sprintf('<h2>%s</h2>', $this->table->getName());
}
private function attachTableContent ()
{
$this->htmlOutput .= '<table class="table table-bordered table-small">';
$this->htmlOutput .= $this->table->getHeader()->drawHeaders();
$this->htmlOutput .= $this->table->getBody()->drawBody();
$this->htmlOutput .= '</table>';
}
}
class HeaderThreeMarshaller
{
public function __invoke (TableHeaderContract $tableHeader)
{
$htmlOutput = '<theader>';
foreach ($tableHeader->getHeaders() as $headTitle) {
if (!empty($headTitle)) {
$htmlOutput .= sprintf('<th>%s</th>', $headTitle);
}
}
$htmlOutput .= '</theader>';
return $htmlOutput;
}
}
class BodyMarshaller
{
public function __invoke (TableBodyContract $body)
{
$htmlOutput = '<body>';
foreach ($body->getRows() as $rowNum => $rows) {
$htmlOutput .= '<tr>';
/**
* @var Row $row
*/
foreach ($rows as $row) {
$htmlOutput .= sprintf(
'<td>%d</td><td>%s</td><td>%d</td>',
$row->getId(),
$row->getTally(),
$row->getTotal()
);
}
$htmlOutput .= '</tr>';
}
$htmlOutput .= '</body>';
return $htmlOutput;
}
}
And here is how you can test its generation. So for the example below:
$table = new Table('Test Example 1', 5, 85);
print $table->draw();
You can copy the code example I created and check its output on a HTML file!
Upvotes: 0
Reputation: 6456
1.You should calculate count of columns: if a count of records is multiple of ten then count of columns is equal count of records / 10 otherwise count of columns is equal count of records / 10 + 1. Code example:
$rowCount = 10;
$colCount = intval($recordCount / $rowCount);
if ($recordCount % $rowCount !== 0 ) {
$colCount++;
}
2.You should calculate index of a row in the table for each element and build array of table rows. This index can be calculated with help the following formula: index of an element % count of rows. Count example:
$rows = [];
for ($i = 0; $i < $recordCount; $i++) {
$index = $i % $rowCount;
$rows[$index][] = [
'Q' => $i+1,
'Tally' => '', // you can set value
'Total' => '', // you can set value
];
}
As can you see this algorithm is very simple and its asymptotic complexity is O(n)
3.You should render header with help count of columns. Code example:
$output .= '<tr>';
for ($i = 1; $i <= $colCount; $i++) {
$output .= '<td scope="col">Q</td>
<td scope="col">Tally</td>
<td scope="col">Total</td>';
}
$output .= '</tr>';
4.You should render other parts of a table with help array of table rows. Code example:
foreach ($rows as $row) {
$output .= '<tr>';
foreach ($row as $element) {
$output .= "<td>{$element['Q']}</td><td></td><td></td>";
}
$output .= '</tr>';
}
Full code:
function buildTable($name, $rowCount, $recordCount)
{
//calculating of count rows
$colCount = intval($recordCount / $rowCount);
if ($recordCount % $rowCount !== 0 ) {
$colCount++;
}
// making of row array
$rows = [];
for ($i = 0; $i < $recordCount; $i++) {
$index = $i % $rowCount;
$rows[$index][] = [
'Q' => $i+1,
'Tally' => '', // you can set value
'Total' => '', // you can set value
];
}
// render header
$output = "<table class='table table-bordered table-small'>
<tr>
<th scope='col' colspan='99'>{$name}</th>
</tr>";
$output .= '<tr>';
for ($i = 1; $i <= $colCount; $i++) {
$output .= '<td scope="col">Q</td>
<td scope="col">Tally</td>
<td scope="col">Total</td>';
}
$output .= '</tr>';
// render other parts of table
foreach ($rows as $row) {
$output .= '<tr>';
foreach ($row as $element) {
$output .= "<td>{$element['Q']}</td><td></td><td></td>";
}
$output .= '</tr>';
}
$output .= "</table>";
return $output;
}
$tablename = 'test';
$recordCount = 25;
$rowCount = 10;
echo buildTable($tablename, $rowCount, $recordCount);
Upvotes: 2
Reputation: 1619
Try this code :
//no. of ques
$total_ques = 45;
//creating array for que no
$que_nos = range(1,(int)$total_ques);
$part = 10;
//splitting array in chunks
$cols = array_chunk($que_nos,$part);
echo '<table border="1" cellpadding="5">';
echo '<tr>';
foreach($cols as $col) {
//Generating heading columns
echo "<td>Q</td>";
echo "<td>Tally</td>";
echo "<td>Total</td>";
}
echo '</tr>';
//data for each row
$row_data = [];
for ($i=0; $i < $part; $i++) {
//temporary variable containing values for each row
$temp_row_data = [];
foreach($cols as $k1 => $col) {
//getting first value of array
$value = reset($col);
$temp_row_data[] = $value ?: '';
if ($value !== false) {
//unset value as it is already processed
unset($cols[$k1][array_search($value,$col)]);
}
}
//storing temporary array in main row array
$row_data[] = $temp_row_data;
}
foreach ($row_data as $key => $cd) {
echo '<tr>';
foreach ($cd as $c) {
echo "<td>{$c}</td>";
echo "<td></td>";
echo "<td></td>";
}
echo '</tr>';
}
echo '</table>';
The output will be like as below in the image
Upvotes: 3