How best to do an array in Access 2013 (1 Viewer)

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
Hi, I want to create an array in an Access table but it doesn't seem that it is possible. Do I really have to manually create all fields in the 'array' as individual fields? BTW, I want the array to be of 26 x 2 (integers). One pair for each letter of the alphabet. Each letter can have 2 different integer values associated with it. Any help or advice would be great. Thanks
Stephen
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:51
Joined
Feb 28, 2001
Messages
27,172
Arrays cannot be reasonably created in a table as a single field. (And any database that allows such a thing violates a basic rule of databases -atomicity.)

You can create a sequence of 26 records with however many fields in each record, but even that seems to suspiciously violate normalization if the fields could have been part of an array. That's not guaranteed, however.

Stephen, for storage of your data array, a table would be appropriate if you put one row of the array in a record. If you are trying to use this in code later, you can build a memory version of the array to be used only at run-time. But perhaps a discussion of your goal would be in order. WHY do you need this array? What (in broad-brush terms) did you plan to do with it?
 

vba_php

Forum Troll
Local time
Today, 03:51
Joined
Oct 6, 2019
Messages
2,880
Hi, I want to create an array in an Access table but it doesn't seem that it is possible.
generally that's right, you can't. you can do many things as a workaround, like Richard already said. one would be putting this in a single field in a single table (based on what you've said you wanted as the content of the array):
Code:
x(25, 50) as variant
alternatively you could do it the "simple-stupid" way in many rows, which is *my* way a lot of times, especially when handing the deliverable off to the customer to carry on:
Code:
x(0, 0) = 1
x(0, 1) = 2
etc.....
Do I really have to manually create all fields in the 'array' as individual fields?
YES. but you should do it in rows instead of fields, otherwise pulling the text out of the table when you run code will be a nightmare.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 04:51
Joined
May 21, 2018
Messages
8,527
Not clear what you are doing, so a better description is needed. Based on what you said I would think the table structure is.

tblArrays:
Code:
  arrayID
  itemLetter
  value1
  value2

so the data looks like

Code:
1 A 123 342
1 B 321 675
1 C 567 890
.....
1 Z 891 654

if I add multiple arrays then the second array is

Code:
2 A 098 356
2 B 789 655
...
2 Z 667 777

Now you can easily read this data and populate real arrays in code by looping the recordset.
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
I want to avoid multiple reads on the database hence wanting an array in a single field on a single row. VBA_PHP, your solution looks to be what I want. But I'm not clear how I would implement this. Would there be one field called 'x' of type variant of length 26 x 10 i.e. 260 which I would then put into an array in VBA when I've read the record? What I have is a series of races and for each race runners are split into teams with a certain number ('n') of runners (male and female) per 'team' (the runners are not named so it takes the first 'n' runners in turn to make each team 'A' for the first 'n', 'B' for the next 'n' etc.). The two fields per team are totals for position and time because results can either accumulate the total time taken for all the runners in the team or the position of each runner in the race. I hope that makes sense. The next stage is to run a report (I suspect using a Pivot table - the next hurdle) to show all the results for each team in each race in the series with the teams being the columns and the races being the races in the series, one column per race with a total column at the end on which the report will be sorted (in ascending order). Again I hope that makes sense.
 

vba_php

Forum Troll
Local time
Today, 03:51
Joined
Oct 6, 2019
Messages
2,880
it makes perfect sense Goody. what does *not* make sense is your desire to do this whole array concept storage in a table field. many *many* people who have posted here have had data similar to yours. and everytime we would tell them to set it up properly, or correct them if they came to us with a set up that was not normal. Same thing applies to you. You can *easily* build your db in such a way that you query out the info you need with regard to races, teams and runners. Your words:
What I have is a series of races and for each race runners are split into teams with a certain number ('n') of runners (male and female) per 'team' (the runners are not named so it takes the first 'n' runners in turn to make each team 'A' for the first 'n', 'B' for the next 'n' etc.).
does make it seem like you would want to pursue an "array-like-driven application", but again that's totally unnecessary. The only question I have about these words of yours is - at what point in the process do you actually have *hard* data you can work with and input into your tables? Because *real* data is what you want in your db, *not* something like " 'n' runners on team B".

But also note that if you're stuck with the data you've mentioned and it will never be clarified like the way I want it to be, you still don't need to be storing array-like code in a table. You can still accomplish the goal of reporting on your data just fine. I've not seen one situation, ever, where someone stored literal VBA code in a table and then used VBA code in a redundant manner to pull it out of the table and run it. That makes 0 sense. The only time I've ever done something similar to that was when I wrote an app years ago whereby VBA code was written to build an entire PHP script, line by line, variable by variable and method by method, and then stored each PHP code line in a separate record (1 field) in 1 table. And that unfortunately is a concept that will be coming into reality as soon as AI gets to the sophistication point where it can write smart code and build apps on its own without the need for us. and that is *exactly* why I posted this thread....to give developers an understanding of 1) the hierarchial structure the drives development platforms so they can use it to create products that differentiate themselves from other people, and 2) the way large corporations will discover they can automate most pattern-like tasks. So much of what we as humans do is pattern-based, and unfortunately that can be easily exploited and learned by a machine.
 
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:51
Joined
Feb 28, 2001
Messages
27,172
Would there be one field called 'x' of type variant of length 26 x 10

You cannot create the structure in a record. 'Variant' is a data type for VBA, not for SQL. It might be possible through a bunch of gyrations with large binary objects, but I suspect that because of the embedded pointers, that wouldn't work very well - if at all.

If you want to minimize reads and writes, then put each row in a record. At the start of your process, read the entire recordset one record at a time and build the array. At the end of the process, go back and update the records in the recordset to match whatever you actually did.

As to WHERE this would go, that depends. If this is something that only a single form would ever use, you could pre-declare that array in the Declaration area at the top of the form's Class Module. If it must be shared, it would have to go in the Declaration area of a general module. Given your desired structure, I would not put this in a TEMPVARS or DICTIONARY object because those generally want scalar values, not arrays. So the only thing matching your requirements that would be available would be a memory array that exists only for the lifetime of its use.
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
OK, so now I am completely confused. Adam (aka vba_php guy) you posted:

generally that's right, you can't. you can do many things as a workaround, like Richard already said. one would be putting this in a single field in a single table (based on what you've said you wanted as the content of the array):
Code:
x(25, 50) as variant

What did you mean by this? I can easily have a record per team per race with a pair of values for each but it looked like your suggestion above would allow a single field in a single table. I'm only using 'n' to indicate it is a variable that the user can define but of course it is defined in the team calculation criteria associated with a series and/race.

The_Doc_Man, I just want to avoid multiple reads on the table if I can avoid it just as it is quicker of course but if that is the only way then sobeit. Adam above seemed to be suggesting it was possible in a single field in a single table but perhaps I misunderstood. :)
 

vba_php

Forum Troll
Local time
Today, 03:51
Joined
Oct 6, 2019
Messages
2,880
OK, so now I am completely confused. Adam (aka vba_php guy) you posted:

What did you mean by this? I can easily have a record per team per race with a pair of values for each but it looked like your suggestion above would allow a single field in a single table. I'm only using 'n' to indicate it is a variable that the user can define but of course it is defined in the team calculation criteria associated with a series and/race.
Goody,

The problem with this whole thread is 2 fold:

  1. You are unsure of how to describe what you want to accomplish.
  2. the people who have offered advice so far are also offbase because they don't know what you're really trying to get at.
I would suggest at this point, because you've gotten so many pieces of feedback from so many people that have different skillsets and disciplines, is to pick one person to go with and communicate with. That way you don't get really confused and give up on your goal here. The purpose of my post was to encourage you to realize the fact that what you want to do is not necessary, and you would do yourself a favor by using tables and relationships as an alternative to storing VBA code in a table and trying to reference it to write VBA code. That would result in virtually the same confusing concept as the ever-so-popular "circular reference error" problem seen so many times by Excel users! Why not make things easy on yourself in this regard? :)
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
Hi Adam, I had no intention of storing VBA code in a table just an array of values. I think that was clear from my original post. "is it possible to store an array of values in a single field and row in an Access table?" You seemed to suggest a solution with your x(25,10) variant but that I have have obviously misunderstood. I then just went on to explain what the application is to give you an insight to the issue. I've decided to go with the record per club per team and just put up with the multiple reads. Thanks anyway for all your help and sorry if you got confused :)
 

vba_php

Forum Troll
Local time
Today, 03:51
Joined
Oct 6, 2019
Messages
2,880
hey no problem. as long as you solve the problem, that's what matters. I have a reputation of going overboard with regard to explaining my viewpoint. so if you have an answer, good for you. :)
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 04:51
Joined
May 21, 2018
Messages
8,527
I just want to avoid multiple reads on the table if I can avoid it just as it is quicker of course but if that is the only way then sobeit.

Sorry, but you are completely wasting you time trying to make a Rude Golberg solution to a non problem. I can guarantee I can build a properly designed database that will blow away any bizarre stored array concept, even if it was possible.

What I have is a series of races and for each race runners are split into teams with a certain number ('n') of runners (male and female) per 'team' (the runners are not named so it takes the first 'n' runners in turn to make each team 'A' for the first 'n', 'B' for the next 'n' etc.).
The two fields per team are totals for position and time because results can either accumulate the total time taken for all the runners in the team or the position of each runner in the race.
I hope that makes sense.
The next stage is to run a report (I suspect using a Pivot table - the next hurdle) to show all the results for each team in each race in the series with the teams being the columns and the races being the races in the series, one column per race with a total column at the end on which the report will be sorted (in ascending order). Again I hope that makes sense.

That report would occur almost instantly using a simple SQL query. Do you have many 100 of thousands of races and teams. If not you are completely wasting time with worrying about speed.

There are times when reading a recordset into an array makes sense for speed purposes. I do this often, but that is usually solving complex optimization or assignment problems. As far as I can tell there is no complex math here, just very simple sql manipulations. If you want help on properly designing the DB we can help, but drop the array idea.

If you want to see how to read data from a properly designed tables and solve a complex optimization using array manipulation:
https://www.access-programmers.co.uk/forums/showthread.php?t=306791&highlight=knapsack
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:51
Joined
Feb 28, 2001
Messages
27,172
Yep, MajP helped by resetting my focus.

If you have 26 records with no more than a very few fields in each, you would rarely if ever notice the speed of an operation. For comparison, I've had queries that had to look through 1500 records to determine eligibility issues for what turned out to be about 40% of the whole table. Took less than two seconds most of the time.
 

vba_php

Forum Troll
Local time
Today, 03:51
Joined
Oct 6, 2019
Messages
2,880
I can guarantee I can build a properly designed database that will blow away any bizarre stored array concept, even if it was possible.
careful my man! You dont wanna become an overbearing a$$ like yours truly do you? Adopting my personality will surely draw fire from Richard at the very least!
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
Thanks MajP. Once I have calculated the results the report is hopefully straightforward as you say. I know what I want to achieve which is half the battle. Just getting used to different tools and I have never coded Pivot tables although have used them quite happily a long time ago! Let me get the data right first and then I'll post again if I need help with the final report output. I have to assume users are complete technophobes. Thanks for the offer of help.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 04:51
Joined
May 21, 2018
Messages
8,527
Just getting used to different tools and I have never coded Pivot tables although have used them quite happily a long time ago!
Based on your description, not sure if you would need a pivot table. It looks standard queries in a report. Might need a xtab query, but I do not see a pivot table. The trick with Access is not to design your tables based on what you want the output to look like. If you do that you get a spreadsheet like solution, which are not useable. Need to ensure simple normalized structure and then you can get the output to be whatever you want.
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
Thanks MajP. Yep, you're right a crosstab query will work just fine! Hope to have a sample report by the end of the weekend. Just looking at Commit and Rollback as there are a couple of tables I will be updating in parallel.
 

GoodyGoody

Registered User.
Local time
Today, 09:51
Joined
Aug 31, 2019
Messages
120
Well, good news. I have the logic at least running and yet to be tested fully but it seems to be generating something akin to sensible results . My last challenge now is how to implement Rollback and Commit. I looked around and got a bit confused by seemingly conflicting examples. In the end I used the dbengine.begintrans , .rollback and .commit methods but it failed in the code below after the first instance of dbengine.rollback on the line intClubID = rs1![RaceClub] with error ' No Current record'. I am assuming that the dbengine.rollback method has discarded the current record marker so I commented them out for now. Am I correct in this assumption because if it is that's a pain as it is going to be difficult to set the current record marker in the recordset since it is generated by a query. I'm hoping that there is some clever way of resetting (or storing) the current record marker. The recordset I am looping through, rs1, I am also updating as I go along and it is these updates I want to roll back if there are not enough runners/athletes for the team. I still want to continue reading through the rs1 recordset of course to create any more potential teams. Do I then need another recordset for the underlying table of rs1 that I update directly because of the affect Rollback has on the current record marker?

Thanks as ever for any guidance. I've put the code below in case it helps:

Private Sub btnCalculateRaceEventTeamResults_Click()

'On Error GoTo ErrorHandler

Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim rs4 As DAO.Recordset
Dim sqlString As String
Dim intTeam As Integer ' Holds the number representing the team 0=A, 1=B, 2=C etc
Dim intTeamID As Integer ' The table "Team" primary key
Dim intTeamTotPos As Integer
Dim intTeamTotSecs As Integer
Dim intTeamCounter As Integer ' How many in the current team
Dim strTeamGender As String
Dim intMaxTeamCounter As Integer
Dim intClubID As Integer

'Make sure a race has been selected
If IsNull(Forms!frmPrintRaceEventTeamResults!cmbRaceName) Or IsNull(Forms!frmPrintRaceEventTeamResults!cmbRaceDate) Then
intAnswer = MsgBox("Please select a valid race", vbCritical)
Exit Sub
End If

intAnswer = MsgBox("You are about to recalculate the team results for this event. Doing so will remove all previous results. Do you wish to Continue", _
vbQuestion + vbYesNo)
'Exit if they don't want to continue
If Not (intAnswer = vbYes) Then
Exit Sub
End If

DoCmd.SetWarnings (WarningsOff) 'This avoids confusing messages to the user that 'n' records will be being updated (or not!)


Set db = CurrentDb()


'First remove all the records for this race event that might have been previously calculated
DoCmd.OpenQuery "qryDeleteRaceEventTeamResults"
Set rs1 = fDAOGenericRst("qryRaceEventTeamResultsIndividual")

'Now read the Team table firsst to get the criteria for the teams
'Then read through the database doing first the teams for the women gender = 'F' and then the men 'M' gender = 'M'
'Write a team record for each set of male or female runners qualify for the team criteria
'Mixed teams will be dealt with later
'If the race is part of a series the series team criteria will take precedence over the race event team criteria

'If there are no records to process just end here
If rs1.EOF Then
intAnswer = MsgBox("There are no records to process for this Event", vbCritical)
Exit Sub
End If

'Read the RaceEvent or Series record to get the Team calclation ID
If rs1![RaceSeries] = 0 Then
sqlString = "SELECT * FROM [RaceEvent] WHERE [ID] = " & rs1![RaceEvent]
Set rs3 = db.OpenRecordset(sqlString, dbOpenDynaset)
rs3.MoveLast 'this will "populate the recordset"
intTeamID = rs3![RaceEventTeamID]
Else
sqlString = "SELECT * FROM [Series] WHERE [SeriesID] = " & rs1![RaceSeries]
Set rs3 = db.OpenRecordset(sqlString, dbOpenDynaset)
rs3.MoveLast 'this will "populate the recordset"
intTeamID = rs3![SeriesTeamID]
End If

'Now read the team table to get the correct criteria

sqlString = "SELECT * FROM [Team] WHERE [TeamID] = " & intTeamID
Set rs4 = db.OpenRecordset(sqlString, dbOpenDynaset)
rs4.MoveLast 'this will "populate the recordset"

rs1.MoveLast 'this will "populate the recordset"
rs1.MoveFirst

'Loop through the runners for the raceevent for each gender to calculate totals for each runner in the team
'Females are first in alphabetical sequence
'Increment the team ID for each new team

intTeamTotPos = 0
intTeamTotSecs = 0
intTeamCounter = 0
intTeam = 0
strTeamGender = rs1![RaceGender]
intClubID = rs1![RaceClub]
If rs1![RaceGender] Like "F" Then
intMaxTeamCounter = rs4![NumOfFemaleAthletes]
Else
intMaxTeamCounter = rs4![NumOfMaleAthletes]
End If
Set rs2 = db.OpenRecordset("TeamResults")
Do While Not rs1.EOF
If Not strTeamGender Like rs1![RaceGender] Or Not intClubID = rs1![RaceClub] Then
' DBEngine.Rollback ' Undo any changes so far as there are not enough runners to form a team
intTeamTotPos = 0
intTeamTotSecs = 0
intTeamCounter = 0
intTeam = 0
intClubID = rs1![RaceClub]
If Not strTeamGender Like rs1![RaceGender] Then
intMaxTeamCounter = rs4![NumOfMaleAthletes]
strTeamGender = rs1![RaceGender]
End If
End If
'DBEngine.BeginTrans 'All database reads and writes will be held until 'Committed'
intTeamCounter = intTeamCounter + 1
intTeamTotPos = intTeamTotPos + rs1![RaceGenderPosition]
intTeamTotSecs = intTeamTotSecs + rs1![RaceTimeSecs]
With rs1
.Edit
![RaceTeam] = intTeam
.Update
End With

If intTeamCounter = intMaxTeamCounter Then
'Insert the team record
With rs2
.AddNew
![TeamSeriesID] = rs1![RaceSeries]
![TeamRaceEventID] = rs1![RaceEvent]
![TeamClubID] = rs1![RaceClub]
![TeamGender] = strTeamGender
![Team] = intTeam
![TeamTotPos] = intTeamTotPos
![TeamTotSecs] = intTeamTotSecs
.Update
End With
'DBEngine.CommitTrans 'Commit the database changes so they are permanent and consistent
intTeamCounter = 0
intTeamTotPos = 0
intTeamTotSecs = 0
intTeam = intTeam + 1
End If
rs1.MoveNext
Loop

DoCmd.SetWarnings (WarningsOn)


Error_Handler_Exit:
On Error Resume Next
If Not rs1 Is Nothing Then
rs1.Close
Set rs1 = Nothing
End If
If Not rs2 Is Nothing Then
rs2.Close
Set rs2 = Nothing
End If
If Not rs3 Is Nothing Then
rs3.Close
Set rs3 = Nothing
End If
If Not rs4 Is Nothing Then
rs4.Close
Set rs4 = Nothing
End If
If Not db Is Nothing Then Set db = Nothing
Exit Sub

ErrorHandler:
'DBEngine.Rollback
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: cmd_AddRec_Click" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Sub
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 04:51
Joined
May 21, 2018
Messages
8,527
The order does not seem to make sense. Not sure what you are trying with the rollback. Should be
1 .beginTrans
your changes
2 .update
normally and If then to determine
3 .commit OR .rollback

It is hard to read without using the # tags at the top of the page. Please repost with tags to see indentation.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 04:51
Joined
May 21, 2018
Messages
8,527
Without seeing the tables this is a little hard to follow. You can post the tables and there are a couple of threads on here on how to scramble data fields. So you could scramble names and other PI. I would avoid looping recordsets to get sums and counts. Build the aggregate queries. Do that in a query or a simple dsum, dcount. I do not think you need to do a rollback. You should be able to determine ahead of time if you have enough using a simple dcount.
 

Users who are viewing this thread

Top Bottom