Excel/Access problem with Rnd()

G

Guest

I have posted a related issue here and in the Excel daoquery thread before,
but I have narrowed down the issue and, with apologies in advance, am
reissuing a new question thread. I am posting in both places in the hopes
that someone has some insight.

I have a test case that randomizes the order of records using Rnd().
Originally this was used in a select query, but in an effort to stabilize the
debugging environment I'm now using it in a maketable query so that viewing
the result each time doesn't re-execute the select and perturb the results.

The original table (called Test) is very simple: two fields, an autonumber
ID field and a number field called Test which I populated with values 1-6 in
six records. So in essence, the value of the Test field equals the value of
the ID field.

I then wrote a VBA routine in Access to populate a new table called Result
from the original Test table; all it does is scramble the order of the
records randomly. The code for the routine is:

Public Sub TestRoutine()
Dim lSQL As String

On Error Resume Next
DoCmd.DeleteObject acTable, "Result"
On Error GoTo 0

lSQL = "SELECT [Test].*,Rnd([ID]) AS Sort INTO [Result] FROM [Test]
ORDER BY Rnd([ID])"
DBEngine(0)(0).Execute lSQL, dbFailOnError

End Sub

I can execute this from the Access VBA IDE Immediate pane and I get a
different table each time; in other words, executing from Access works as
expected.

I then try to run this routine from Excel VBA. You can't just run in the
Immediate pane because of all the overhead hooking up to Access, so I have a
very simple routine called Test that I wrote in Excel VBA:

Public Sub Test()
Dim lAccess As New Access.Application
Dim lPath As String

lPath = ThisWorkbook.Path
lAccess.OpenCurrentDatabase lPath & "\Test.mdb"
lAccess.Run "TestRoutine"

lAccess.Quit

Set lAccess = Nothing

End Sub

All this does is run the same TestRoutine sub that I was running from the
Access Immediate pane. I can now run this Excel Test sub in the Excel
Immediate pane.

Remember that when I ran this from Access, it correctly generated a new
random-ordered table each time. But when I run from Excel, it generates the
same table each time, in the same order: 4,5,2,3,1,6. The problem is that the
Rnd() function generates the same number every time. For example, the Rnd()
function associated with the 4th original record (which ends up at the top in
the new table) is ALWAYS 0.01401764154.

So even though Rnd() is only being executed in Access as part of an SQL
statement in a routine in Access, calling that routine in Excel makes it run
differently. The Help file in Excel describes its Rnd() function as having
the same semantics as defined in Access.

I've tried using Randomize to reseed the RNG in both Access and Excel; that
doesn't help.

By the way, this problem also happens (in fact my original problem happened)
when simply defining a query with Rnd() in it and using the database
import/update feature in Excel -- in other words, no VBA was used at all, it
was simply executing a query (transparently) and putting the results into
Excel. The query, when executed in Access, worked; when updating through
Excel returned identical results each time. I only went to VBA in an attempt
to control the process explicitly as a workaround, which didn't work.

Any idea how to get Rnd() to generate random sequences in this situation?

Thanks! I'm tearing my hair out here.
 
G

giorgio rancati

Hi BnB,

try this
----
Public Sub TestRoutine()
Dim lSQL As String

On Error Resume Next
DoCmd.DeleteObject acTable, "Result"
On Error GoTo 0

lSQL = "SELECT [Test].*, Rnd(([ID]+Timer())*-1) AS Sort INTO [Result]
FROM [Test] ORDER BY Rnd(([ID]+Timer())*-1)"
DBEngine(0)(0).Execute lSQL, dbFailOnError


End Sub
----

bye
--
Giorgio Rancati
[Office Access MVP]

"BnB" <[email protected]> ha scritto nel messaggio
[CUT]
 
G

Guest

Brilliant... that seems to have worked.

Sooo... the conclusion is that there is some kind of bug in Rnd() in this
usage since it won't generate a new random number each time with a positive
argument like it's supposed to. So rather than using the system-generated and
-seeded random number, you're forcing a seed in the actual Rnd call by using
a negative argument that will always be different (for each time and for each
record).

btw, just to test if I was crazy, I tested Rnd(3) in the immediate panes of
Excel and Access; works fine. So it seems to be related to the interaction
between Excel and Access.

Thank you thank you thank you. [Starts putting hair back in.]


giorgio rancati said:
Hi BnB,

try this
----
Public Sub TestRoutine()
Dim lSQL As String

On Error Resume Next
DoCmd.DeleteObject acTable, "Result"
On Error GoTo 0

lSQL = "SELECT [Test].*, Rnd(([ID]+Timer())*-1) AS Sort INTO [Result]
FROM [Test] ORDER BY Rnd(([ID]+Timer())*-1)"
DBEngine(0)(0).Execute lSQL, dbFailOnError


End Sub
----

bye
--
Giorgio Rancati
[Office Access MVP]

"BnB" <[email protected]> ha scritto nel messaggio
[CUT]
I have a test case that randomizes the order of records using Rnd().

Public Sub TestRoutine()
Dim lSQL As String

On Error Resume Next
DoCmd.DeleteObject acTable, "Result"
On Error GoTo 0

lSQL = "SELECT [Test].*,Rnd([ID]) AS Sort INTO [Result] FROM [Test]
ORDER BY Rnd([ID])"
DBEngine(0)(0).Execute lSQL, dbFailOnError

End Sub
[CUT]

Any idea how to get Rnd() to generate random sequences in this situation?

Thanks! I'm tearing my hair out here.
 
G

giorgio rancati

Hi BnB,

In the Access query the Rnd base value is set when starts jet's instance.
In Excel application you start a new jet's instance every time that you run
the *Sub Test()*, for this motive the sortorder is always equal

(My English isn't good, I hope to have explained.)
:)
 
G

Guest

Your explanation makes sense, although Randomize seems like it should have
helped there because it's supposed to reseed the RNG with a timer-related
seed if used without an argument (which is what I did). At least that's how I
understood the documentation. So each instance, being at a different time,
should have reseeded with a new seed, but that didn't seem to happen.

Anyway, you've been a HUGE help. Thanks again. All my problems are solved.

(Well, the Access-related ones anyway... For today... :) )


giorgio rancati said:
Hi BnB,

In the Access query the Rnd base value is set when starts jet's instance.
In Excel application you start a new jet's instance every time that you run
the *Sub Test()*, for this motive the sortorder is always equal

(My English isn't good, I hope to have explained.)
:)
--
Giorgio Rancati
[Office Access MVP]
BnB said:
Brilliant... that seems to have worked.

Sooo... the conclusion is that there is some kind of bug in Rnd() in this
usage since it won't generate a new random number each time with a positive
argument like it's supposed to. So rather than using the system-generated and
-seeded random number, you're forcing a seed in the actual Rnd call by using
a negative argument that will always be different (for each time and for each
record).

btw, just to test if I was crazy, I tested Rnd(3) in the immediate panes of
Excel and Access; works fine. So it seems to be related to the interaction
between Excel and Access.

Thank you thank you thank you. [Starts putting hair back in.]
 
T

Tom Ellison

That's a very, very good catch!

Tom Ellison


giorgio rancati said:
Hi BnB,

In the Access query the Rnd base value is set when starts jet's instance.
In Excel application you start a new jet's instance every time that you
run
the *Sub Test()*, for this motive the sortorder is always equal

(My English isn't good, I hope to have explained.)
:)
--
Giorgio Rancati
[Office Access MVP]
BnB said:
Brilliant... that seems to have worked.

Sooo... the conclusion is that there is some kind of bug in Rnd() in this
usage since it won't generate a new random number each time with a positive
argument like it's supposed to. So rather than using the system-generated and
-seeded random number, you're forcing a seed in the actual Rnd call by using
a negative argument that will always be different (for each time and for each
record).

btw, just to test if I was crazy, I tested Rnd(3) in the immediate panes of
Excel and Access; works fine. So it seems to be related to the
interaction
between Excel and Access.

Thank you thank you thank you. [Starts putting hair back in.]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top