Excel CSV numbers to normal string for PHP - php

I'm working on an import module where an admin can import rows of client information (including the client's ID Number which is a 13 digit numeric value) from a CSV file.
The problem appears that Excel converts the numbers to look like 8.88888E+12 if the value was 8888881111088 and I need to validate that number (even if it's a string) to match back to a previous entry in the database).
Unfortunately I cannot rely on the admin to convert these entries within Excel to a string so I am looking for a way in PHP to convert the incorrect values to a 13-digit number/string.
Any suggestions would greatly be appreciated!
Here is a sample of the script I am using:
<?php
// $data contains the rows returned from the CSV file:
foreach ($data AS $k => $v) {
/* $v['id_number'] is 8.88888E+12 but in the database it's stored correctly
* as 888888111088. I need to match the imported value from the CSV to the row
* in the database.
*
* I need to convert 8.88888E+12 back to 888888111088.
*/
if (strlen(str_replace(" ", "", $v['id_number'])) != 13) {
$this->importValidateRules[$k] = "The ID number (" . $v['id_number'] . ") is invalid. It must be 13 characters long.";
}
// Continue with model validation:
}
?>

In general putting ' sign in cell before the number could enforce Excel to use the value as text. If you could manipulate the original xls or ask user to do it before saving to csv it would work {e.g. having a new column in and putting onto B1 cell =CONCATENATE("'",A1) }
"Figuring out" from csv+php won't work (precision lost already).

Related

SQLite3::exec(): unrecognized token: "'Date"

I get the error message SQLite3::exec(): unrecognized token: "'Date" when I insert a command into a SQLite database.
If I have the SQL commands echoed and execute them via the console, this also works. The data for this comes from a dbase database.
If I enter a string for fieldname the insert commands will work.
$field=unpack( "a11fieldname/A1fieldtype/Voffset/Cfieldlen/Cfielddec", substr($buf,0,18));
$db = new SQLite3('databases/test.db');
$sqlCode .= "INSERT INTO HEADER (name) VALUES ('".$field['fieldname']."');";
$db-> exec($sqlCode);
Would be that much easy to use prepare satement against sql injections
If I enter a string for fieldname the insert commands will work
make sure if fieldname is a text value
I am using pdo :
$sqlCode = "INSERT INTO header VALUES (:name)";
$query = $db->prepare($sqlCode);
$query->bindValue(':name', $field['fieldname'], SQLITE3_TEXT);
$result = $query->execute();
EDIT : Error says unrecognized token Date, So, if fieldname is a date you might need to change SQLITE3_TEXT to SQLITE3_BLOB OR SQLITE3_INTEGER Usualy not needed.
But you need to insert date into date column not into name column
EDIT 2 :
it's a bit complicated.
See here for a full description of the dbf file format.
So it would be best if you could use a library to read and write the dbf files.
If you really need to do this yourself, here are the most important parts:
Dbf is a binary file format, so you have to read and write it as binary. For example the number of records is stored in a 32 bit integer, which can contain zero bytes.
You can't use string functions on that binary data. For example strlen() will scan the data up to the first null byte, which is present in that 32 bit integer, and will return the wrong value.
If you split the file (the records), you'll have to adjust the record count in the header.
When splitting the records keep in mind that each record is preceded by an extra byte, a space 0x20 if the record is not deleted, an asterisk 0x2A if the record is deleted. (for example, if you have 4 fields of 10 bytes, the length of each record will be 41) - that value is also available in the header: bytes 10-11 - 16-bit number - Number of bytes in the record. (Least significant byte first)
The file could end with the end-of-file marker 0x1A, so you'll have to check for that as well.
See asked : binary safe write on file with php to create a DBF file
Final Word : you need DBF library
Data File Header Structure

Append row in a spreadsheet as the values were user entered

I have an array of strings and I need to append it in a spreadsheet, from the first to the n-th column according to the size of the array.
The strings could represent several type of values, e.g. numbers, dates and so on, so they must be put in the sheet as user entered to keep their meaning.
As far as I understand, the Google APIs offer two ways to append values, but none of them seems to be suitable for this case. Here's the issues I encountered:
Using Google_Service_Sheets_AppendCellsRequest
The problem with this method is that I cannot find a way to set the values as user entered. Here is a code sample:
// Build the CellData array
$values = array();
foreach( $ary_values AS $d ) {
$cellData = new Google_Service_Sheets_CellData();
$value = new Google_Service_Sheets_ExtendedValue();
$value->setStringValue($d);
$cellData->setUserEnteredValue($value);
$values[] = $cellData;
}
// Build the RowData
$rowData = new Google_Service_Sheets_RowData();
$rowData->setValues($values);
// Prepare the request
$append_request = new Google_Service_Sheets_AppendCellsRequest();
$append_request->setSheetId(0);
$append_request->setRows($rowData);
$append_request->setFields('userEnteredValue');
// Set the request
$request = new Google_Service_Sheets_Request();
$request->setAppendCells($append_request);
(full working code is here)
Even using CellData.setUserEnteredValue, the data is interpreted as string because one have to set the values using ExtendedValue.setStringValue (or the other supported methods, i.e. setBoolValue, setFormulaValue, setNumberValue).
Using spreadsheets.values.append
Using this method I can have the data rendered as user entered, but the "appending" is done in the wrong place in several cases. As stated in the documentation:
The input range is used to search for
existing data and find a "table" within that range. Values will be
appended to the next row of the table, starting with the first column
of the table.
So this method is meant to behave in a different way from the previous one, and that leads to problem for me.
This is a piece of code that should do what I want:
$body = new Google_Service_Sheets_ValueRange([
'values' => [ $array_values ]
]);
$params = [
'valueInputOption' => 'USER_ENTERED'
];
// the n-th column
$end_column = chr( ord('A') + count($array_values));
$result = $sheet_service->spreadsheets_values->append(
$fileId,
$sheetName . "!A1:" . $end_column . "1",
$body,
$params
);
Indeed, it works fine but with some exceptions, e.g.:
if the cell A1 is empty, the append method will put the values starting at column 2 (see this example to understand why).
if I have some written rows, then an empty row, then other written rows, the append method will "fill the gap" instead of putting the values after the very last written row.
Am I doing some errors? Is there a way to make what I want using either one or the other method?
To recap:
the values must be considered as user entered (e.g. a number or a date should be interpreted as such)
the values must be written in the row after the last non-empty cell, starting at column one
the append operation must be atomic (i.e. sending one request to get the last non-empty cell row and then sending another request to write data into that is not an option, because in the meantime another user could put data there)
Any advice is welcome!

Display BigInt DataType of length 10 in Excel Sheet using PHP

I want to make a excel file by fetching data from database. Every thing works fine but the phone number field return unknown value in excel sheet but it displays correct value in browser.
<?php
include('connection.php');
header( "Content-Type: application/vnd.ms-excel" );
header( "Content-disposition: attachment; filename=spreadsheet.xls" );
$q = mysql_query("select * from members order by id desc");
echo 'First Name' . "\t" . 'email' . "\t" . 'Phone' . "\t". 'address' . "\t". 'Membership Number' . "\t". 'Membership Category' . "\n";
while($r = mysql_fetch_array($q))
{
$name = $r['name'];
$email = $r['email'];
$phone = $r['phone'];
$address = $r['address'];
$mem_num = $r['mem_num'];
$mem_cat = $r['mem_category'];
echo "$name"."\t"."$email"."\t"."$phone"."\t"."$address"."\t"."$mem_num"."\t"."$mem_cat"."\n";
}
mysql_close($con);
?>
I believe you are confusing data-types here. A phone number for instance, is not a number. But it's called a number! Yeah I know, because it has a lot of numbers in it, but still, it isn't a number... Why?
A phone number is indeed constructed of a set of numerals - the symbols that represent a number - but that doesn't make it a number yet. Compare letters and words; a word is constructed of a set of letters, but not every set of letters is a word. For example: dfslkwpdjkcnj is not a word, not in a language I know of at least... And if it would be a number, how would you add-up two phone numbers? Or how would you divide a phone number by another one? Would that be something like [grandma's phonenumber] / [mom's phonenumber] = [my phonenumber]?
So, to store a phone number in a database, a varchar would be a more suitable column type. For example international phone numbers start with either a + sign, or double zero (00). Both of them can not be stored in a numeral field type. The + isn't a numeral sign, or is used to designate a positive number, and will be cut off. Leading zero's in a number have no function at all, and will be cut off as well...
So bottom line; in your database, use a varchar to store a phone number, and use conversion functions to format a phone number to your liking. There are almost certainly a dozen of algorithms to be found to format a phone number to some kind of a standardized format.
Then back to your excel: your aren't creating an excel file, but a csv file, and you're giving it an excel mime-type. But that would be the same to give someone a cd and say it is a dvd. If you put the cd in a dvd player, it will almost certainly be able to play it, but it is mere luck then wisdom that it does.
Creating an excel file isn't as easy as setting the mime-type, as you can't expect the browser to know how to convert text to an excel file, as it does not know about excel's internals. So if you reaaally want to create an excel file, and set the data types of certain columns, use a library like phpExcel or any other available, if you don't want to create a library yourself that is.
have you tried expanding(stretching) phone column in your excel file? sometime if column is small and numbers are big, excel displays number like(1.23+09) this.
If stretching column does not work. you can convert numbers into string and then put them in excel file
sorry i can't add this in comment as i don't have privilege to comment yet.
If with your API you are able to format cells, that's what you would need to do. You are storing your phone number as a BigInt instead of as a String. I have always stored phone numbers as Strings.
Excel is interpreting your data correctly--as a number, not as text. If you wish to continue to store your phone number as a BigInt (which I don't recommend), you would need to convert it to a String before writing it out to Excel. Or, if your API permits, write it out to Excel as a number, but then apply cell formatting to bring it to the formatting you expect.

Inserting decoded JSON string into MYSQL where JSON string variable length

I can decode and insert JSON strings into mysql. Thats fine where the JSON data does not vary in length
I am currently trying to insert train timetable JSON strings into mysql
So for each journey I get a single JSON string (I am decoding them individually as thousands of them)
Each JSON string gives a Unique Identifier for the train , some operating characteristics, etc but more importantly the locations it visits and timings at those locations.
My problem is that there may be one location or 100 locations - it varies every time
The below code shows me decoding and echo'ing the tiploc code (ie locaton).
How do I insert into mysql a varying amount of locatons...........ie location 1 , location 2 , location 3 etc....................against one single UID. I have put ?????next to that bit of code below. Also don't know how I tell my database to expect 1 to 100 locations?
Thanks
if (($data->JsonScheduleV1->CIF_stp_indicator)<>"C") {
$uid=($data->JsonScheduleV1->CIF_train_uid);
echo "NEW LINE OF JSON";
foreach ($data->JsonScheduleV1->schedule_segment->schedule_location
as $route) {
$tiploc=$route->tiploc_code;
echo $tiploc;
?????mysqli_query($mysql_link,"INSERT INTO teststp (uid,tiploc)
VALUES ('$uid','$tiploc')");
}
}

Leading zeros in an extracted Excel file from database using PEAR

In the admin section of my website there is a button that extracts an Excel file with data from my database. In reality, it is an Excel file that is created upon clicking the button using PEAR. I use an SQL query to get the information necessary from my SQL Server 2008 database.
One of the columns named 'number1' contains a number ranging from 1-9999. I have been looking for a way to have it put zeros in front of the numbers when it doesnt have 4 digits already, but I've had no luck until now. For example, if the number in the database is 12, I would like it to show as 0012 in my Excel sheet.
currently the code used is the following:
if ($j == 15){
$worksheet->write($variable1, $j , $variable2[$i][$j], $text222);
}
where $variable1 = 0; $variable2 = ("my sql query")
Your help is appreciated.
EDIT: ANSWER(S)
$number = str_pad($value, 4, '0', STR_PAD_LEFT);
OR
JAGAnalyst's answer, the one I actually used in my code.
Alternatively, you can also edit your SQL query to return a four-character text string instead of a number, including the replacement function, i.e.
, CASE
WHEN Len(number1) = 1 THEN '000' + CAST(number1 AS VARCHAR(4))
WHEN Len(number1) = 2 THEN '00' + CAST(number1 AS VARCHAR(4))
WHEN Len(number1) = 3 THEN '0' + CAST(number1 AS VARCHAR(4))
ELSE CAST(number1 AS VARCHAR(4))
END AS NEW
This will actually alter the value that is extracted, rather than simply changing the format.

Categories