Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsFormsForms ProgrammingQueriesModules / DAO / VBAReports / PrintingMacrosDatabase DesignSecurityConversionImporting / LinkingSQL Server / ADPMultiuser / NetworkingReplicationSetup / ConfigurationDeveloper ToolkitsActiveX ControlsNew UsersGeneral 1General 2
Access DirectoryToolsTutorialsUser Groups
Related Topics
SQL ServerOther DB ProductsMS OfficeMore Topics ...

MS Access Forum / Importing / Linking / June 2006

Tip: Looking for answers? Try searching our database.

values in an exported file

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Patrick - 21 Jun 2006 20:20 GMT
Hey!

I've exported a file from access using transferspreadsheet.  One field in
access which has a data type of "Number" with a field size of "Single" is
populated by an update query to be 0.04. When I export the spreadsheet to
excel the value becomes:   0.0399999991059303 which rounds to .04 in excel
but when I use this percentage against large numbers and then sum them I have
issues.  

I must be missing something obvious.

Thank you!

Patrick
John Nurick - 22 Jun 2006 06:37 GMT
This happens because the value 0.04 can't be stored exactly as a binary
number (just as many values - 1/3 for example) can't be stored exactly
as a decimal number. Excel uses Doubles for all numeric data, and the
extra precision of Double over Single is exposing the issue.

Try changing the Access field type to Number (Double). That way, you
have the same precision in both places.

>Hey!
>
[quoted text clipped - 10 lines]
>
>Patrick

--
John Nurick [Microsoft Access MVP]

Please respond in the newgroup and not by email.
onedaywhen - 22 Jun 2006 14:19 GMT
> This happens because the value 0.04 can't be stored exactly as a binary
> number (just as many values - 1/3 for example) can't be stored exactly
> as a decimal number.

Are you sure?

> Try changing the Access field type to Number (Double).

If this value is intended to be 0.04 throughout, and I think from the
OP's description it is, then I would recommend the OP changes the data
type to DECIMAL(p, 2).

I have two reasons for this recommendation

1) If the nature of the data is reality is 'numeric two fixed decimal
places' then the OP should model it as such; inexact data types
introduce a risk, from which the OP has already been bitten.

2) If the OP already has data that is REAL (Single) in nature then
casting it to FLOAT (Double) will not improve the situation, whereas I
think DECIMAL will i.e.

CSNG(0.0399999991059303) will be coerced to DECIMAL 0.04 and remain as
0.04 when coerced to FLOAT (Double) on export to Excel

whereas

CSNG(0.0399999991059303) will remain unchanged when cast/coerced as
FLOAT (Double) in Access and Excel and the problem remains.

> Excel uses Doubles for all numeric data

Actually, Excel's CURRENCY is a numeric type that is fixed point (i.e.
not a floating point) in nature, with a fixed scale (decimal places) of
four.

Jamie.

--
John Nurick - 22 Jun 2006 22:01 GMT
>> Excel uses Doubles for all numeric data
>
>Actually, Excel's CURRENCY is a numeric type that is fixed point (i.e.
>not a floating point) in nature, with a fixed scale (decimal places) of
>four.

Do you mean VBA's Currency data type, or some way (new to me) of forcing
Excel to store numeric values in cells in a fixed-point format? If the
latter, how does one control it?

--
John Nurick [Microsoft Access MVP]

Please respond in the newgroup and not by email.
onedaywhen - 23 Jun 2006 09:11 GMT
> >Excel's CURRENCY is a numeric type that is fixed point (i.e.
> >not a floating point) in nature, with a fixed scale (decimal places) of
[quoted text clipped - 3 lines]
> Excel to store numeric values in cells in a fixed-point format? If the
> latter, how does one control it?

I mean the latter i.e. an in-cell fixed point type.

In MS Jet terms, the Excel data types are CURRENCY, DATETIME, LOGICAL
(yes/no), FLOAT (Double), MEMO and NVARCHAR(255).

For an Access man such as yourself, I know of no better way to create a
CURRENCY column than this:

CREATE TABLE
[Excel 8.0;DATABASE=C:\DropMe.xls;].TestExcel (
cur_col CURRENCY,
float_col FLOAT
);

As usual, here's some VBA to create a test database (i.e. Excel) and
demonstrate that the type is indeed CURRENCY in nature:

Sub ExcelCurrency()
Dim con
Set con = CreateObject("ADODB.Connection")
With con
 .ConnectionString = _
     "Provider=Microsoft.Jet.OLEDB.4.0;" & _
     "Data Source=C:\DropMe.mdb"
 .Open

 ' Create test 'database' (new workbook)
 ' and 'table' (new sheet and Defined Name)
 .Execute _
 "CREATE TABLE" & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel" & _
 " (cur_col CURRENCY, float_col FLOAT);"

 ' Create test data (Banker's rounding
 ' should round 0.00025 to 0.0002)
 .Execute _
 "INSERT INTO [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel (cur_col, float_col)" & _
 " VALUES (0.00025, 0.00025);"

 ' Create test data (Banker's rounding
 ' should round 0.00035 to 0.0004)
 .Execute _
 "INSERT INTO [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel (cur_col, float_col)" & _
 " VALUES (0.00035, 0.00035);"

 Dim rs
 Set rs = .Execute( _
 "SELECT cur_col, float_col FROM" & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel;")

 MsgBox _
 "cur_col" & vbTab & "float_col" & vbCr & _
 rs.GetString
 rs.Close
   
End With
End Sub

Jamie.

--
onedaywhen - 23 Jun 2006 09:26 GMT
> In MS Jet terms, the Excel data types are CURRENCY, DATETIME, LOGICAL
> (yes/no), FLOAT (Double), MEMO and NVARCHAR(255).

This is the closest I could find to any details on MSDN:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcje
tmicrosoft_excel_data_types.asp


No mention of MEMO but it can be explicitly created e.g.

Sub ExcelMemo()
Dim con
Set con = CreateObject("ADODB.Connection")
With con
 .ConnectionString = _
     "Provider=Microsoft.Jet.OLEDB.4.0;" & _
     "Data Source=C:\DropMe.mdb"
 .Open

 .Execute _
 "CREATE TABLE" & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel2" & _
 " (text_col NVARCHAR(255), memo_col MEMO);"

 ' This will succeed, showing the MEMO
 ' col can accommodate 300 characters
 .Execute _
 "INSERT INTO " & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel2 (text_col, memo_col)" & _
 " VALUES (STRING$(255, 'x')," & _
 " STRING$(300, 'x'));"

 ' This will succeed, showing the NVARCHAR
 ' col cannot accommodate 300 characters
 .Execute _
 "INSERT INTO " & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel2 (text_col, memo_col)" & _
 " VALUES (STRING$(300, 'x')," & _
 " STRING$(300, 'x'));"
   
 .Close
End With
End Sub

--

Jamie.

--
John Nurick - 23 Jun 2006 20:49 GMT
Hi Jamie,

>  .Execute _
>  "INSERT INTO [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
>  ".TestExcel (cur_col, float_col)" & _
>  " VALUES (0.00025, 0.00025);"

Having installed Office 2003 SP2 I can't do this sort of thing any more.
I hacked your sub so it executed only the CREATE TABLE statement (adding
a TEXT column for the hell of it), and then opened the resulting .xls
file and typed the 0.00025 and 0.00035 into the first two blank rows.

The values in cur_col were not rounded, and the values in text_col were
recognised as numbers, so it seems that - as I thought - even though the
Excel driver has a concept of column types, Excel itself doesn't.

Going a step further, I re-hacked your code to connect to the worksheet
and display the data (using $ on the sheet name to get the UsedRange
because I hadn't updated the "TextExcel" named range when I typed in the
data):

 Dim rs
 Set rs = .Execute( _
 "SELECT cur_col, float_col, text_col FROM" & _
 " [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".[TestExcel$];")

 MsgBox _
 "cur_col" & vbTab & "float_col" & vbTab & "text_col" & vbCr & _
 rs.GetString
 rs.Close

Again, the values in cur_col were not rounded.

So I surmise that the situation is this:
1) It's possible to use the Excel driver to execute a CREATE TABLE
statement that specifies column types.

2) Doing so does nothing to restrict the kinds of data that can be
inserted into the columns via the Excel UI or VBA.

3) But provided you don't drop the connection and aren't using an
up-to-date installation of Access 2002 or 2003, the Excel driver will
coerce values you inserte or update by executing SQL statements.

Here's a couple of things I'd try if I had an older machine here:

a) modify your test sub to execute this:

 "INSERT INTO [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel (cur_col, float_col)" & _
 " VALUES (12345679012345.1234, 12345679012345.1234);"

Then dive into VBA and check the Formula and Value properties of the
cells. If the CREATE TABLE created a currency column, the cur_col value
will have all 19 digits, while float_col will lose the last three or so.

b) close the connection, then re-connect and try to execute something
like this

 "INSERT INTO [Excel 8.0;DATABASE=C:\DropMe.xls;]" & _
 ".TestExcel (cur_col, float_col)" & _
 " VALUES ('This is a numeric value', 'Me too');"

--
John Nurick [Microsoft Access MVP]

Please respond in the newgroup and not by email.
onedaywhen - 28 Jun 2006 10:29 GMT
> I hacked your sub so it executed only the CREATE TABLE statement (adding
> a TEXT column for the hell of it), and then opened the resulting .xls
> file and typed the 0.00025 and 0.00035 into the first two blank rows.

When you use a CREATE TABLE in SQL DDL where the target workbook does
not exist, a new workbook will be created containing one worksheet and
a Defined Name ('named range') limited to the rows created. If you only
executed the CREATE TABLE and no INSERT INTO statements, the extent of
the Excel 'table' will limited to the column headers. Therefore, when
you typed data into the 'first two blank rows' I'm guessing they were
outside of the Excel 'table'.

> Going a step further, I re-hacked your code to connect to the worksheet
> and display the data (using $ on the sheet name to get the UsedRange
> because I hadn't updated the "TextExcel" named range when I typed in the
> data):

Jet must allow for uncontrolled editing in the Excel interface and it
does it using the data itself and TypeGuessRows. I'm guessing you are
already aware of this
(http://www.dicks-blog.com/archives/2004/06/03/external-data-mixed-data-types/)
so I won't elaborate.
Looking your approach more generally, I think you may be expecting too
much <g>. It is a 'feature' of Excel that it does not have strong data
typing. Using Jet to manipulate Excel data can provide a fair degree of
data typing. However, opening the Excel workbook in Excel rightly frees
it of the Jet data typing.

Apologies if I did get your hopes up :)

Jamie.

--
John Nurick - 28 Jun 2006 20:57 GMT
>Looking your approach more generally, I think you may be expecting too
>much <g>. It is a 'feature' of Excel that it does not have strong data
[quoted text clipped - 3 lines]
>
>Apologies if I did get your hopes up :)

I'll take this as accepting that Excel doesn't have "an in-cell fixed
point type".

--
John Nurick [Microsoft Access MVP]

Please respond in the newgroup and not by email.
onedaywhen - 29 Jun 2006 08:32 GMT
> I'll take this as accepting that Excel doesn't have "an in-cell fixed
> point type".

Hmm, I think this is about perception.

I can create an Excel column of numeric values (double float), even set
Data Validation for the column to 'Decimal', yet I can still paste a
300 character text value into that column. Would you thereby conclude
that Excel does not have an in-cell numeric type?

In Excel it holds true that if you circumvent the functionality that
provides data typing (cell format, Data Validation, Jet interface, etc)
then you have no data typing.

To employ a Jet analogy, if date/time values are persisted as FLOAT
(Double) does this mean Jet has no distinct DATETIME data type?

Again I make the point that weak data typing is a feature of Excel i.e.
people want, expect and like it that way. Excel weakly types the
column/cell and tries to 'format' the value supplied according to that
type. However, unlike, say Jet with an .mdb file which throws an
exception when the data cannot be coerced to the type, Excel will
effectively change the data type of the column to fit the data. In
fact, I think it is true that of the Excel interface that values
inserted into cells are not coerced at all (loss of accuracy associated
with double float, cell size limit and such aside).

I don't want to argue. If your perception is that Excel has no currency
type then based on your criteria (strongly typed, does not change type
based on data supplied) then you are right. This is not a "let's agree
to differ" stance, rather a "we're looking at things differently" one.

Jamie.

--
Patrick - 22 Jun 2006 16:15 GMT
Thank you!

> This happens because the value 0.04 can't be stored exactly as a binary
> number (just as many values - 1/3 for example) can't be stored exactly
[quoted text clipped - 23 lines]
>
> Please respond in the newgroup and not by email.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.