Changing format of CSV from MySQL DB using PHP - php

I found a similar question but there was no solution due to lack of information.
I have the code below which outputs data from the connected MySQL DB to a formatted CSV file in the following format…
First Name:Surname:GCNumber:Dept:Start Date:Introduction:Theory:Fire Safety:Governance:
John:Smith:123456:HR:03/08/2013:Pass:Pass:Fail:Pass:
Jane:Watson:123445:IT:03/08/2013:Pass:Fail:Pass:Pass:
Mark:Byron:123442:IT:03/08/2013:Fail:Fail:Not Done:Not Done:
: = used just to show each column
It just outputs all the rows and columns that are in the database in the same structure, and renaming the column headers to be more friendly when imported into excel.
What I need is to change to format of this output to the following…
First Name:Surname:GCNumber:Dept:Email:Start Date:Module:Status:
John:Smith:123456:HR:03/08/2013:Introduction:Pass:
John:Smith:123456:HR:03/08/2013:Theory:Pass:
John:Smith:123456:HR:03/08/2013:Fire Safety:Fail:
John:Smith:123456:HR:03/08/2013:Governance:Pass:
Jane:Watson:123445:IT:03/08/2013:Introduction:Pass:
Jane:Watson:123445:IT:03/08/2013:Theory:Fail:
Jane:Watson:123445:IT:03/08/2013:Fire Safety:Pass:
Jane:Watson:123445:IT:03/08/2013:Governance:Pass:
Mark:Byron:123442:IT:03/08/2013:Introduction:Fail:
Mark:Byron:123442:IT:03/08/2013:Theory:Fail:
Mark:Byron:123442:IT:03/08/2013:Fire Safety:Not Done:
Mark:Byron:123442:IT:03/08/2013:Governance:Not Done:
: = used just to show each column
So Rather than one entry for each person, and results of each module they have done I need it to be a separate entry for each module that person has done.
In total there are more fields to this DB and 35 modules but I've cut this down for illustration purposes here.
Being a bit of a newbie with PHP etc I'm struggling to get my head around how to do this.
Is this possible or would it be easier to try and change the structure of the DB to be in the desired format?
Any help or pointers in the right direction would be great.
Tony
<?php
function exportMysqlToCsv($table,$filename = 'db-snapshot.csv')
{
$sql_query = "select fldFirstname as 'First Name',
fldSurname as 'Surname',
fldGMCNumber as 'GCNumber',
fldDestDept as 'Dept',
fldStartDate as 'Start Date',
fldModule1 as 'Introduction',
fldModule2 as 'Theory',
fldModule3 as 'Fire Safety',
fldModule4 as 'Governance'
from $table";
// Gets the data from the database
$result = mysql_query($sql_query);
$f = fopen('php://temp', 'wt');
$first = true;
while ($row = mysql_fetch_assoc($result)) {
if ($first) {
fputcsv($f, array_keys($row));
$first = false;
}
fputcsv($f, $row);
} // end while
$size = ftell($f);
rewind($f);
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: $size");
// Output to browser with appropriate mime type, you choose ;)
header("Content-type: text/x-csv");
// header("Content-type: text/csv");
// header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=$filename");
fpassthru($f);
exit;
}
?>

You can use UNIONS for this:
SELECT fldFirstname as 'First Name', fldSurname as 'Surname',
fldGMCNumber as 'GCNumber', fldDestDept as 'Dept',
fldStartDate as 'Start Date', fldEndDate as 'End Date',
'Introduction' as 'Module', fldModule1 as 'Status' FROM records
UNION
SELECT fldFirstname,fldSurname,fldGMCNumber,fldDestDept,fldStartDate,fldEndDate,
'Theory',fldModule2 FROM records
UNION
SELECT fldFirstname,fldSurname,fldGMCNumber,fldDestDept,fldStartDate,fldEndDate,
'Fire Safety',fldModule3 FROM records
UNION
SELECT fldFirstname,fldSurname,fldGMCNumber,fldDestDept,fldStartDate,fldEndDate,
'Governance',fldModule4 FROM records
ORDER BY Surname, `First Name`, Module;
SQL Fiddle example

I would use a pivot on my query to the DB. Check under
If I have a MySQL table looking something like this
So you would basically create a table with rows describing your module:
Module
1 | Introduction
2 | Theory
3 | Fire Safety
4 | Governance
Then join it to table above and use a "Case" syntax to achieve your request.

Related

Inserting a table record (log entry) upon CSV download

I'm fairly new to PHP and this is my first-ever stackoverflow question:
I want to make it easy for a user to know when data has changed since they last downloaded a CSV file from the application I'm building. The CSV export works and I can determine whether there are any rows whose timestamp is after the timestamp stored in an export log table. My problem is that I cannot figure out how to store the timestamp in the log table. When a user clicks the link to export the file, the code below executes to produce the file. The very last four lines are my attempt to make the log entry. $con is valid and works and my method works in a regular PHP page, but I can't figure out how to make it work in the CSV download page and I don't know of any other way to make the entry when the user clicks to download. I am open to ideas for the best way to do this.
I really appreciate your time -- thanks in advance!
<?php
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=speakers.csv");
header("Pragma: no-cache");
header("Expires: 0");
require_once("../scripts/dbcon.inc.php");
require_once("../scripts/presentersessions.inc.php");
$query = "SELECT DISTINCT sp.person_id, CONCAT(p.person_display_name, ' ', p.person_last_name) person_name, '' session_titles, p.person_bio FROM person p INNER JOIN presenters sp ON p.person_id = sp.person_id ORDER BY p.person_last_name, p.person_display_name";
$result = mysqli_query($con, $query) or die('failed query: '.$query);
$num_rows = mysqli_num_rows($result);
$output = fopen("php://output", "w");
fputcsv($output, array("Item ID (Optional)","Name","Sub-Title (i.e. Location, Table/Booth, or Title/Sponsorship Level)","Description (Optional)","Location/Room"));
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
#echo '"","'.htmlspecialchars($row['person_display_name']).' '.htmlspecialchars($row['person_last_name']).'","'.htmlspecialchars($row['session_title']).'","'.htmlspecialchars($row['person_bio']).'"\n"';
$person_id = $row['person_id'];
$row['person_name'] = $row['person_name'];
$row['session_titles'] = presenter_sessions($conference_id, $person_id);
$row['person_id'] = '';
fputcsv($output, $row);
}
date_default_timezone_set('US/Eastern');
$export_timestamp = date("Y-m-d H:i:s");
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('$export_type', '$export_timestamp', {$_SESSION['valid_accbo_person_id']})";
$result_insert_log_entry = mysqli_query($con, $query_insert_log_entry);
make sure you set this vaiable $export_type and $_SESSION['valid_accbo_person_id'] is accessible on this page.
I think the problem is in this line -
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('$export_type', '$export_timestamp', {$_SESSION['valid_accbo_person_id']})";
remove those single quote from variables like below -
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('{$export_type}', '{$export_timestamp}', '{$_SESSION['valid_accbo_person_id']}')";

fputcsv adds unwanted Validation comment at top of file

I need csv output with column headers and comma delimited data. The fputcsv function is working right except that it places a "Validation" comment at the top of the output file:
<!-- Validated at 2016-04-17 00:32:00 -->
This line causes the file to fail when updating my data. If I remove the comment, the file works. Does anyone know how to generate fputcsv output without the comment line?
Here is code
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=gmail.csv');
$output = fopen('php://output', 'w');
fputcsv($output, array('Name', 'Given Name', 'Family Name', 'Group Membership', 'E-mail 1 - Value'));
// Connect to host and open db
include('includes/connect.php');
//Set Date range. Determines current renewal year for Select statement
$year = date('Y') - 1;
$group = date('Y')." member";
/* Select specified member data */
$sql = "SELECT firstLast, firstName, lastName, email, status, gmail, payDate
FROM membership, memberDues
WHERE payDate >= '$year-10-01' AND ID = memberID
ORDER BY lastName, firstName";
$result = mysqli_query($dbCnx, $sql);
while ($row = mysqli_fetch_assoc($result)) {
$gmailArray = array( $row['firstLast'], $row['firstName'], $row['lastName'], "$group", $row['email'] );
fputcsv($output, $gmailArray);}
I discovered the problem. My security include (which I hadn't looked at in a few years), inserts that Validation line if user has permission to view the page. I guess it's useful to review old bits of plug&play code every so often to help trouble shoot these types of annoyances.

output column names from custom query in mysql

I've created a small input form for a custom sql query using php. I've been able to output the results to a csv form, however I'm having some trouble including the headers in the output file.
I've had no trouble creating an array of the header rows, but I'd like to be able to create the headers out of the query itself.
This is what I've used:
$output = fopen('php://output', 'w');
//get query data
$qs = $_GET['custom'];
$rs = mysqli_query($dbc, $qs)
or die ('Error querying database');
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=query.csv');
$csv = fopen('php://output', 'w');
while ($row = mysqli_fetch_assoc($rs)) {
fputcsv($csv, $row);
}
fclose($csv);
What I want is a way of inputting the rows from the select before the content of the query (which comes through fine).
I know this will work for set headers if I put it in before the first fputcsv line:
fputcsv($csv, array('col1', 'col2', 'col3', [etc...] ));
but it is only because I define the fields in the array.
What I'm looking for is way to identify the columns in the query and use them as column headers.
I've been attempting to do something with a query that would just get the column names, and then feed that as an array but I can't seem to get it to work. Something like this:
SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'database_name'
and column_name in ($query)
where the $query variable is similar to the $qs query above, but alas no luck. Does anyone know how to do this? Thanks in advance.
fputcsv($csv, array_keys($row)); at the beginning?

inserting sql output rows to excel file

i have 150 rows and 40 columns in a sql table..i am displaying the entire table in a web page..now,what i want to do is create a link on that web page that will take the entire table and insert it in an excel file(dosn't matters if it creates a new excel file,or modifies sum exisiting one)...now i can do it manually by using(PHPExcel library)," objPHPExcel->setCellValue('C5', $v) "...but i would have to write this like 40 times(change '$v' variable in every statment) nd its inside a loop that will run 150 times..hence i dont wanna do it this way..
now i wanted to know if i can insert the table,row by row in the excel sheet..like when i insert a row,it will insert the entire cells of d row..that way it will be pretty easy..so i wanted to know if there any specific commands for doing this..
if not,wat other alternatives do i have of doing this..all i want to do is to export the entire sql table to an excel file using php..
So use the fromArray() method that PHPExcel thoughtfully provides that allows you to write a whole row or whole block of cells in one call from an array.
Looking at the examples and reading the documentation always helps
Additional note
Incidentally, $objPHPExcel->setCellValue('C5', $v) will only work if $objPHPExcel is a worksheet, most of the examples use $objPHPExcel for the workbook (ie the collection of worksheets) so don't get confused
EDIT
For fetching the results from your database, use
sqlsrv_fetch_array($tsql, SQLSRV_FETCH_ASSOC)
or
sqlsrv_fetch_array($tsql, SQLSRV_FETCH_NUMERIC)
EDIT 2
Check how the database is set to handle NULL returns; but using
$objPHPExcel->getActiveSheet()->fromArray($rows, 0, 'A'.$rowCNT);
should set all NULL values from the database result to 0 value in PHPExcel
The easiest way is to export a .csv file, which can also be read by excel.
All you have to do is create this page :
<?
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
$link = mysql_connect('db', 'dblogin', 'dbpasswd');
#mysql_select_db('dbname') or die( "Unable to select database");
$query=mysql_query("SELECT * FROM whatever");
$j=0;
$nbField = mysql_num_fields($query);
while ($j < $nbField) {
echo mysql_field_name($query,$j).";";
$j++;
}
echo "\n";
while ($row = mysql_fetch_array($query, MYSQL_NUM)) { echo implode(";", $row)."\n"; }
?>
Then you insert a link pointing directly to this php page, it will download the csv file.

Export MySql table to CSV?

So, I have searched most of the answers here on stack and google and anywhere I could think of. There are plenty of answers indeed, but none have the structure I need.
Al my code looks like this:
$sql = "SELECT * FROM users WHERE user_level = '$level' ORDER BY user_username DESC";
if ($stmt = $this->connect->prepare($sql)) {
$stmt->bind_result($id);
$stmt->execute();
while ($row = $stmt->fetch()) {
$stmt->bind_result($id);
$users[] = $id;
}
$stmt->close();
$length[] = sizeof($users);
} else {
$error = true;
$message['error'] = true;
$message['message'] = CANNOT_PREPARE_DATABASE_CONNECTION_MESSAGE;
return json_encode($message);
}
I'm using mysqli and stmt in all of my code, so I would like to keep it like this all the way.
So, I understand that I cannot have the CSV file where I have my action button to download it. But the thing is that my action button is part of a form, so I guess that instead of $_GET on the page I have the CSV I will have $_POST.
And my question, how do I loop through all database ( this needs to be depending on a column, a level ) and take all that data organized in a CSV file and than download it ? But this needs to be as the structure I have for my functions, I don't want to use db_query("SELECT * FROM {loreal_salons}"); per say or other like that.
Use the following :
// Setup the headers to force download of CSV
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
// loop your records here and output as comma separated
echo $row['col1'].",".$row['col3'].",".$row['col3']."\n";
If you want to loop over all the database, I think the key for what you want to do is :
SHOW TABLES - http://dev.mysql.com/doc/refman/4.1/en/show-tables.html
.. to loop in all the tables
SHOW COLUMN - http://dev.mysql.com/doc/refman/5.0/en/show-columns.html
.. to loop in all the column of a specific table

Categories