I have a task to deliver a numeric/decimal value as part of a fixed length text file. These values will take the following form:
10 chars, w/last 5 chars representing the decimal portion of the string. These will all be positive numbers.
A few examples:
0.123 = "0000012300"
1.0 = "0000100000"
123.456 = "0012345600"
234 = "0023400000"
The numeric data resides in an Access database formatted as numbers (double).
My current thought is:
Retain the orignal numeric data in one table
Convert to TEXT strings via query, save to a second table
Export to a fixed width flat file using MSAccess export function
Can anyone suggest a reasonable approach to produce the necessary 10 character TEXT conversion?
Thanks!
Perhaps just multiply by 100000 and format?
Format(x * 100000, "0000000000")
Related
I'm writing a low level tool to scan and recover data from damaged Jet4 MDB files. I'm scanning through pages, parsing Rows, and decoding columns.
If I have the raw 8 byte value for Datetime fields, how can I convert this to a string representation of the date such as "MM-DD-YY HH:MM:SS"?
If I have the raw 4 byte value for a Number field with Single field size and 3 decimal places, how can I convert this value to a float/double?
Are there any documents that describe how all of the access fields are encoded and stored on disk?
Thank you.
If I have the raw 8 byte value for Datetime fields, how can I convert this to a string representation of the date such as "MM-DD-YY HH:MM:SS"?
Access stores Date/Time values as 64 bit (8 byte) Double values in little-endian format. The integer portion represents the number of days before or after the Access "epoch" (1899-12-30 00:00:00) and the absolute value of the fractional portion represents the time portion for that day (e.g., 0.5 = Noon). So, for example, in Python we would convert the bytes into a datetime value like so:
from datetime import datetime, timedelta
import struct
# bytes as retrieved from .accdb or .mdb file
d_as_bytes = b'\x35\x07\x2F\x2C\x93\x63\xDD\xC0'
d_as_double = struct.unpack('<d', d_as_bytes)[0] # -30094.29957175926
d_integer_part = int(d_as_double) # -30094
d_fractional_part = abs(d_as_double - d_integer_part) # 0.29957175926
access_epoch = datetime(1899, 12, 30)
d = access_epoch + timedelta(days=d_integer_part) + timedelta(days=d_fractional_part)
print(d) # 1817-08-08 07:11:23
No. The JET format is proprietary of Microsoft and not documented.
As for the Date data type, this is simply a double.
Neither double nor single carry a format. As you mention, these a standard floating point values.
I am having trouble with a sequence of code that is not reading the NVARCHAR length of my variables (they are barcode strings). We have two different barcodes and the inventory system I have set up measures only the format of the original one (has 7 characters). The new barcode has 9 characters. I need to run a loop value through each barcode input, hence how I have set up this line of script.
I originally thought that a DATALENGTH or LEN function would suffice but it seems that it is only measuring the variable as an integer, not the 7 characters in the string. If anybody has any input of how to manipulate my code sequence or a function that will measure a variables nvarchar length, it would more than appreciated!
CASE WHEN #BarcodeID = LEN(7)
THEN UPPER(LEFT(#BarcodeID,2))+CONVERT(nvarchar,RIGHT(#BarcodeID,5)+#LoopValue-1)
ELSE UPPER(LEFT(#BarcodeID,3))+CONVERT(nvarchar,RIGHT(#BarcodeID,6)+#LoopValue-1) END
Once again, the LEN(7) function in the beginning seems to be my issue.
Perhaps what you're trying to do is actually
CASE WHEN LEN(#BarcodeID) = 7
By using #BarcodeID = LEN(7) you are basically testing to see if the #BarcodeID variable is equal to 1 because the LEN() function, "Returns the number of characters of the specified string expression." It is implicitly converting 7 to a one-character string.
I am using an external program to run a simulation which returns to me a csv file containing output data. I need to read the data from this file into my fortran program, which analyses and optimizes the input conditions to rerun the external program.
The CSV file has say 20 columns and 70 rows. Each column contains output data for a specific parameter. Now since that program is not written by me, I cannot control the precision of the output values. So in many cases the external program truncates the number of digits after the decimal it they are zero. So it is possible in run number 1, a certain field has 3 digits after the decimal, but has only 2 digits after the decimal in run number 2.
What am I supposed to do for this? I cannot use the read command since in that I need to specify in advance the number of digits my program has to read.
I basically need a way for my program to identify data between commas and read a value or varying precision between the commas.
For input, the decimal part of a format specifier is only used if the input field does not contain a decimal point.
For the last few decades (since the demise of punched cards), users typically expect that a numeric value that doesn't contain a decimal point is an integer value. Consequently, for input, format specifications for real numbers should always have .0 for their decimal part.
For example, after:
CHARACTER(4) :: input
REAL :: a, b
input = '1 '
READ (input, "(F4.0)") a
READ (input, "(F4.1)") b
a will have the value 1.0, and b will have the value 0.1.
(For input, it doesn't particularly matter which particular real data descriptor is used (F, E, D, or G) - they all behave the same regardless of the nature of the input.)
So, for input, all you have to worry about is getting the field width right. Once you have read a record into a string this is easy enough to do by using the INDEX intrinsic.
I am currently importing a data set that includes currency values into an Access database. Although I've read that I should be using the decimal data type for currency, can I not use double to cut down on the file size if the values are rounded to the nearest dollar?
As far as I can tell, the issue with using double for currency is due to rounding, but I won't be doing calculations on the data directly. Any calculations will be done by the application/user.
Similarly, as the data is fixed-length, some of the decimal values are represented by whole numbers. For example, some fields may contain a value of 12345, but the actual value is 12.345. This requires that I import the data and then update the values; dividing by 1000 in the example above.
Will using double in this fashion cause rounding errors as well?
Yes, divisions can and will introduce rounding errors.
You want to use "currency" for ANY kind of business software. In fact if you don't have a currency data type then you use SCALED integers (you scale the results). You thus store
$123.52
As
1235200
(Assuming 4 decimal places)
The reason of course is "real" numbers in computers are only a representation and are only approximate – they are subject to rounding.
This is SIMPLE code:
Public Sub TestAdd()
Dim MyNumber As Single
Dim i As Integer
For i = 1 To 10
MyNumber = MyNumber + 1.01
Debug.Print MyNumber
Next i
End Sub
Here is the actual output of the above:
1.01
2.02
3.03
4.04
5.05
6.06
7.070001
8.080001
9.090001
10.1
Imagine the above – after just 7 SIMPLE and SILLY additions we already getting WRONG answers. And VBA even in Excel will do the SAME. So as noted, we are using 0.01, but it only approximate! (so while we assume this value is 1/100th, it only approximate when using the "real" format in computers.
So computers cannot and do NOT store real numbers to an exact precision. You get rounding errors as a result.
For payroll or anything to do with business applications and money you have to use scaled integers else your tables and accounting and even reports will NOT add up and you experience rounding errors.
I cannot think of any benefits in terms of storage space unless you storing many millions of rows of data. MUCH worse is if you export this data to some other system, then exporting "real" numbers can introduce all kinds of artifacts and even exponents when exporting - use currency - you be safe in what you see and have.
Similar to this question, I have a CSV of currency rates which up to 9 decimal places accuracy.
For example : 0.558659218 , 4470.011076 , 7.02E-05, 0.000641138, 20832.46989
Which data type should I use for the column ?
I tried FLOAT , DOUBLE and DECIMAL(11,11), they produce one of the following warnings:
Out of range value for column 'column_name' at row X
Value truncated for column 'column_name' at row X
when I use SHOW WARNINGS command.
FYI, The SQL statement is as follow (but I guess it is not related):
LOAD DATA LOCAL INFILE 'currency.csv' INTO TABLE the_currency FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' (currency_code, currency_buyin, currency_buyout);
Sample data of the CSV is as follow:
PHP,41.46218559,0.024118362
PKR,95.71731228,0.010447431
PLN,3.2056255,0.311951599
PYG,4470.011076,0.000223713
QAR,3.641148462,0.274638623
RON,3.524472347,0.283730415
RSD,87.59544136,0.011416119
RUB,31.41607934,0.031830834
RWF,626.1686594,0.001597014
SAR,3.750383024,0.266639432
SBD,7.130814403,0.140236436
SCR,13.08102784,0.076446592
SDG,4.412494807,0.226629162
SEK,6.683528257,0.149621571
SGD,1.221878378,0.81841206
SHP,0.623503208,1.603840987
SLL,4349.905174,0.00022989
SOS,1615.486542,0.000619009
SPL,0.166666667,6
SRD,3.274628066,0.305378193
STD,18949.99968,5.28E-05
SVC,8.75,0.114285714
MySQL version: 5.5.34-0ubuntu0.12.04.1 and I'm working in console command.
You need DECIMAL(22,11) if you want 11 digits before as well as after the decimal place. DECIMAL(11,11) doesn't have any storage for digits before the decimal place, and is scarcely even valid at all.
For storing decimal or currency values, DECIMAL or NUMERIC (largely equivalent) are the way to go. Conversion rates are conceptually a little bit different -- since occasionally, they could be variable by much wider factors -- but DECIMAL could be a reasonable place to start, since at least it gives you accurate decimal math results.
The alternative would be DOUBLE (FLOAT does not have very good precision), which would allow conversion rates between hyper-inflated currencies to be stored; however, mixing float-point scaling into 'decimal' math requires a well-defined rounding strategy on output.
Decimal is what you need. The parameters are length then decimal places. Decimal(length,decimal place)
Example decimal(4,2) = max value is 99.99
Decimal(6,2) = max value is 9999.99
Hope this helps.