Array in an array
#1
Happy Year of the Rabbit. Back to work and also back to programming. The holiday break was nice....

So I am trying to rack my head how to store this. Let me show what I have and then maybe someone can call me an idiot and point out an eaiser way of making everything work  Big Grin

The gradebook:

[Image: image.png]

As we can see I am going for something a little more complicated than just enter numbers and call it a day. I want it to be flexiable. Able to add and drop students. Being pulled from the report side of the program

The student data:

Code: (Select All)
TYPE NameListType 'Used for the student name database
    PinYinName AS STRING * 20
    FirstName AS STRING * 20
    MiddleName AS STRING * 20
    LastName AS STRING * 20
    Year AS INTEGER
    Month AS INTEGER
    Day AS INTEGER
    HouseColor AS STRING * 8
    MomName AS STRING * 30
    MomPhone AS STRING * 20 'Saved as string to support symbols and international prefixes
    MomEmail AS STRING * 38
    DadName AS STRING * 30
    DadPhone AS STRING * 20
    DadEmail AS STRING * 38
    UID AS INTEGER
END TYPE

The key I believe is to have a unique id number for each student (UID), positive values will be current students and deleted students will have the value made negative. So we can keep grades with names by having the grade database match this one.

Ok so far....

This is where I run into trouble, one assignment, has details and many students with multiple details. How to combine?

Assignment file (Master):
 
Code: (Select All)
TYPE MasterAssignmentType 'Each entry needs to be defined before use with slave
    ARName AS STRING * 20 'Assignment report name
    ADName AS STRING * 10 'Assignment display name (short name)
    AType AS UNSIGNED BYTE 'Assignment Type (Completeion, formative, summative, etc.)
    ACat AS STRING * 20 'Assignment Category (subject, unit, etc)
    AColor AS UNSIGNED BYTE 'Color coding assignment headers and for grouping for reports
    ACode AS UNSIGNED BYTE 'Reserved
    APts AS UNSIGNED INTEGER 'Total points allowed
END TYPE

Slave file (for student details):
Code: (Select All)
TYPE SlaveAssignmentType 'Each student would require one with use with master
    UID AS INTEGER 'UID will match the stuedent name list to match results, negative UID means deleted and we will ignore it on display and reports
    MPts AS UNSIGNED INTEGER 'Points earned for each particular students
    Flags AS UNSIGNED BYTE 'See below for codes
    Flags2 AS UNSIGNED BYTE ' Reserved
    Notes AS STRING * 512 'Comments for a student's work
END TYPE

'====================Flag codes====================
'1   - Late (Turned in late)                      |
'2   - Absent on due date (ignore due date)       |
'4   - Incomplete (turned in but not done)        |
'8   - Missing (Not turned in)                    |
'16  - Excused/Exempt                             |
'32  - Ignore score internally for avg, etc.      |
'64  - Remove from reports (ignore externally)    |
'128 - Reserved                                   |
'==================================================

Now this is where I am in trouble.

Now I could make a file for each student with the slave but that seems.... excesive. I tried to combine both with an array but, as far as I know, it doesn't work. I want to do something like SlaveFile (UIDs(40), 500) with 40 being for UIDs and 500 for the UDT SlaveFile (something like an array in an array or jagged array). I just don't know the context for this or the workaround to get what I want....

Tried it out in a smiple way and it doesn't work the way I thought it would

Code: (Select All)
OPTION _EXPLICIT

TYPE Test
    X AS INTEGER
    y AS INTEGER
    z AS STRING
END TYPE

TYPE UID
    ID AS INTEGER
END TYPE

DIM AS INTEGER abc(1 TO 4)
DIM AS Test xyz(1 TO 10, abc())

abc(3) = 2
xyz(1, abc(1)).X = 5
xyz(1, abc(2)).y = 3

PRINT xyz(1, abc(1)).X
PRINT xyz(1, abc(2)).y
PRINT abc(3)
PRINT xyz(1, abc(4)).X


Like I said, there is likely a much easier way (I can be a stubborn Polock after all and make things more complicated than I need to!) 

You guys are amazing and I look forward to your wisdom and advide!  Big Grin
Reply
#2
Hi @NasaCow

As you know, we can't do arrays in arrays, so there is no simple solution you are missing.

You can store an array into a string using a Join$ function, just give it an array and a delimiter to separate the different values. 

It's brother is a Split Sub that takes the string and breaks it back up into an array: you give it a dynamic array name to load and tell it what the string is that contains the array and the delimiter used.

Here are the Join$ and Split routines I use:
Code: (Select All)
' note: I buggered this twice now, FOR base 1 array REDIM MyArray (1 to 1) AS ... the (1 to 1) is not same as (1) which was the Blunder!!!
'notes: REDIM the array(0) to be loaded before calling Split '<<<< IMPORTANT dynamic array and empty, can use any lbound though
'This SUB will take a given N delimited string, and delimiter$ and create an array of N+1 strings using the LBOUND of the given dynamic array to load.
'notes: the loadMeArray() needs to be dynamic string array and will not change the LBOUND of the array it is given.  rev 2019-08-27
Sub Split (SplitMeString As String, delim As String, loadMeArray() As String)
    Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
    curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim)
    dpos = InStr(curpos, SplitMeString, delim)
    Do Until dpos = 0
        loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
        arrpos = arrpos + 1
        If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
        curpos = dpos + LD
        dpos = InStr(curpos, SplitMeString, delim)
    Loop
    loadMeArray(arrpos) = Mid$(SplitMeString, curpos)
    ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
End Sub

Function Join$ (arr() As String, delimiter$)
    Dim i As Long, b$
    For i = LBound(arr) To UBound(arr)
        If i = LBound(arr) Then b$ = arr(LBound(arr)) Else b$ = b$ + delimiter$ + arr(i)
    Next
    Join$ = b$
End Function

I will be surprised if you get this in one go and if your array is an UDT (User Desigined Type) it's more complicated still.

I am wondering if I went over something like this when you were last here. The Join$ and Split Routines work very well as I have done GUI and Interpreter with them!

A further complication is if you want to file all this, and why not! Then you have to use fixed strings or some fancy Binary file header.
b = b + ...
Reply
#3
An array in an array... could a multi-dimensional array work here? Say, make a two dimensional array of the SlaveAssignmentType, with the first dimension being indexed to the MasterAssignmentType and the second dimension to the NameListType. The order depending upon which is most likely to need REDIMing during use, should that be necessary. REDIMing the second dimension is trivially easy using REDIM _PRESERVE, but REDIMing the first dimension would require a bit more effort; copying, REDIMing then restoring the copy to the original array.

That was how I approached doing an RPG character generator that juggled multiple characters at one time, each of which had multiple data points that each had to be unique to them.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#4
(02-15-2023, 02:43 AM)OldMoses Wrote: An array in an array... could a multi-dimensional array work here? Say, make a two dimensional array of the SlaveAssignmentType, with the first dimension being indexed to the MasterAssignmentType and the second dimension to the NameListType. The order depending upon which is most likely to need REDIMing during use, should that be necessary. REDIMing the second dimension is trivially easy using REDIM _PRESERVE, but REDIMing the first dimension would require a bit more effort; copying, REDIMing then restoring the copy to the original array.

That was how I approached doing an RPG character generator that juggled multiple characters at one time, each of which had multiple data points that each had to be unique to them.

In a nutshell, this is what I am trying to do but I am not seeing how to index the array to two different UDT. Could provide a code snippet on how to create and change elements? I understand what you are say but having a hard time to see how to code it.


On further reflection what you said and it got me thinking. I could index INSIDE the slave file, it just needs to be a standard array and could get large (number of students times number of assignments). I just needed to hear different ideas from different people to think how to make it work. I think this would work.

Code: (Select All)
TYPE MasterAssignmentType 'Needed to populate the top (assignment list)
    ARName AS STRING * 20 'Assignment report name
    ADName AS STRING * 10 'Assignment display name (short name)
    AType AS UNSIGNED BYTE 'Assignment Type (Completeion, formative, summative, etc.)
    ACat AS STRING * 20 'Assignment Category (subject, unit, etc)
    AColor AS UNSIGNED BYTE 'Color coding assignment headers and for grouping for reports
    ACode AS UNSIGNED BYTE 'Reserved
    APts AS UNSIGNED INTEGER 'Total points allowed
    AID AS INTEGER 'Unique assignment ID
END TYPE

TYPE SlaveAssignmentType 'Needed to fill in the gradebook
    UID AS INTEGER 'UID will match the stuedent name list to match results, negative UID means deleted and we will ignore it on display and reports
    AID AS INTEGER 'Know which student points are going with each assignmnet
    MPts AS UNSIGNED INTEGER 'Points earned for each particular students
    Flags AS UNSIGNED BYTE 'See below for codes
    Flags2 AS UNSIGNED BYTE ' Reserved
    Notes AS STRING * 512 'Comments for a student's work
END TYPE

Adding an assignment ID, I can use the UID and AID like an (X,Y) and print the proper numbers and flags into each box. Thanks for pointing me in the proper direction! Big Grin Big Grin Big Grin
Reply
#5
I was going to propose using _MEM but...

I was able to note the following:

Code: (Select All)
DIM AS INTEGER abc(1 TO 4)
DIM AS Test xyz(1 TO 10, abc())

That can't be done; at declaration BASIC needs to know what is the extent of the array. That is until something like "variants" and object-like variables is figured out into this implementation.

To try to respond to that, I devised this:

Code: (Select All)
TYPE cardty
    nam AS STRING * 16
    quant AS INTEGER
    e AS _MEM
END TYPE

DIM SHARED card(1 TO 10) AS cardty

RANDOMIZE 1000

card(1).nam = "spade"
card(1).quant = 3
create_card 1
random_card 1
PRINT "The first card for "; card(1).nam; " is "; obtain_card(1, 1)
PRINT "The last card for "; card(1).nam; " is "; obtain_card(1, 3)

set_card 1, 3, 22
PRINT "The last card for "; card(1).nam; " was changed to "; obtain_card(1, 3)

delete_card 1
END

SUB create_card (which AS INTEGER)
    SHARED i0 AS INTEGER
    card(which).e = _MEMNEW(card(which).quant * LEN(i0))
    _MEMFILL card(which).e, card(which).e.OFFSET, card(which).quant, 0 AS INTEGER
END SUB

SUB random_card (which AS INTEGER)
    SHARED i AS INTEGER, i0 AS INTEGER
    FOR i = 1 TO card(which).quant
        _MEMPUT card(which).e, card(which).e.OFFSET + (i - 1) * LEN(i0), INT(RND * 52 + 1) AS INTEGER
    NEXT
END SUB

SUB delete_card (which AS INTEGER)
    _MEMFREE card(which).e
END SUB

SUB set_card (which AS INTEGER, subscr AS INTEGER, valu AS INTEGER)
    SHARED i0 AS INTEGER
    _MEMPUT card(which).e, card(which).e.OFFSET + (subscr - 1) * LEN(i0), valu AS INTEGER
END SUB

FUNCTION obtain_card% (which AS INTEGER, subscr AS INTEGER)
    SHARED i0 AS INTEGER
    obtain_card = _MEMGET(card(which).e, card(which).e.OFFSET + (subscr - 1) * LEN(i0), INTEGER)
END FUNCTION

It's a bit confusing to follow along. Using subprograms makes code easier to read, to make things look as much as possible like multiple-dimension arrays.

Note the UDT variable "cards" is declared with "DIM SHARED" to make life easier into the subprograms. Also note the target type is always "INTEGER" in the _MEM workings, hence the "SHARED i0 AS INTEGER" appearing in a lot of places. The type has to be changed there as well as the last parameter to _MEMFILL, _MEMGET and _MEMPUT. Cannot be an UDT.

With this code, doing:

acard = obtain_card(1, 3)

would be like trying to do:

acard = test(1).abc(3)

in code (according to above) that actually is not possible in QB64(PE).

This code could benefit from some range-checking and other things to make it robust.
Reply
#6
(02-15-2023, 03:17 AM)NasaCow Wrote:
(02-15-2023, 02:43 AM)OldMoses Wrote: An array in an array... could a multi-dimensional array work here? Say, make a two dimensional array of the SlaveAssignmentType, with the first dimension being indexed to the MasterAssignmentType and the second dimension to the NameListType. The order depending upon which is most likely to need REDIMing during use, should that be necessary. REDIMing the second dimension is trivially easy using REDIM _PRESERVE, but REDIMing the first dimension would require a bit more effort; copying, REDIMing then restoring the copy to the original array.

That was how I approached doing an RPG character generator that juggled multiple characters at one time, each of which had multiple data points that each had to be unique to them.

In a nutshell, this is what I am trying to do but I am not seeing how to index the array to two different UDT. Could provide a code snippet on how to create and change elements? I understand what you are say but having a hard time to see how to code it.


On further reflection what you said and it got me thinking. I could index INSIDE the slave file, it just needs to be a standard array and could get large (number of students times number of assignments). I just needed to hear different ideas from different people to think how to make it work. I think this would work.

Code: (Select All)
TYPE MasterAssignmentType 'Needed to populate the top (assignment list)
    ARName AS STRING * 20 'Assignment report name
    ADName AS STRING * 10 'Assignment display name (short name)
    AType AS UNSIGNED BYTE 'Assignment Type (Completeion, formative, summative, etc.)
    ACat AS STRING * 20 'Assignment Category (subject, unit, etc)
    AColor AS UNSIGNED BYTE 'Color coding assignment headers and for grouping for reports
    ACode AS UNSIGNED BYTE 'Reserved
    APts AS UNSIGNED INTEGER 'Total points allowed
    AID AS INTEGER 'Unique assignment ID
END TYPE

TYPE SlaveAssignmentType 'Needed to fill in the gradebook
    UID AS INTEGER 'UID will match the stuedent name list to match results, negative UID means deleted and we will ignore it on display and reports
    AID AS INTEGER 'Know which student points are going with each assignmnet
    MPts AS UNSIGNED INTEGER 'Points earned for each particular students
    Flags AS UNSIGNED BYTE 'See below for codes
    Flags2 AS UNSIGNED BYTE ' Reserved
    Notes AS STRING * 512 'Comments for a student's work
END TYPE

Adding an assignment ID, I can use the UID and AID like an (X,Y) and print the proper numbers and flags into each box. Thanks for pointing me in the proper direction! Big Grin Big Grin Big Grin

You're welcome.

I was envisioning something like the following

Code: (Select All)
TYPE NameListType 'Used for the student name database
    PinYinName AS STRING * 20
    FirstName AS STRING * 20
    MiddleName AS STRING * 20
    LastName AS STRING * 20
    Year AS INTEGER
    Month AS INTEGER
    Day AS INTEGER
    HouseColor AS STRING * 8
    MomName AS STRING * 30
    MomPhone AS STRING * 20 'Saved as string to support symbols and international prefixes
    MomEmail AS STRING * 38
    DadName AS STRING * 30
    DadPhone AS STRING * 20
    DadEmail AS STRING * 38
    UID AS INTEGER
END TYPE

TYPE MasterAssignmentType 'Needed to populate the top (assignment list)
    ARName AS STRING * 20 'Assignment report name
    ADName AS STRING * 10 'Assignment display name (short name)
    AType AS _UNSIGNED _BYTE 'Assignment Type (Completeion, formative, summative, etc.)
    ACat AS STRING * 20 'Assignment Category (subject, unit, etc)
    AColor AS _UNSIGNED _BYTE 'Color coding assignment headers and for grouping for reports
    ACode AS _UNSIGNED _BYTE 'Reserved
    APts AS _UNSIGNED INTEGER 'Total points allowed
    AID AS INTEGER 'Unique assignment ID
END TYPE

TYPE SlaveAssignmentType 'Needed to fill in the gradebook
    UID AS INTEGER 'UID will match the stuedent name list to match results, negative UID means deleted and we will ignore it on display and reports
    AID AS INTEGER 'Know which student points are going with each assignmnet
    MPts AS _UNSIGNED INTEGER 'Points earned for each particular students
    Flags AS _UNSIGNED _BYTE 'See below for codes
    Flags2 AS _UNSIGNED _BYTE ' Reserved
    Notes AS STRING * 512 'Comments for a student's work
END TYPE

'Say you have 50 students
DIM NL(50) AS NameListType

'Each student is required to complete 30 assignments
DIM MA(30) AS MasterAssignmentType

'Create a slave assignment indexed to each student and assignment
DIM SA(30, 50) AS SlaveAssignmentType

'The AID & UID would be referenced by the first and second elements of SA respectively
'each student then has a SlaveAssignmentType record for each MasterAssignmentType
'reports can be generated by a nested loop that can check for SGN(NL(x).UID) < 0

FOR student% = 1 TO UBOUND(NL)
    IF NL(student%).UID < 0 THEN _CONTINUE 'student record deleted, skip to next record
    FOR assign% = 1 TO UBOUND(MA)
        'do stuff with all data referenced by SA(assign%, student%) or NL(student%) or MA(assign%)
    NEXT assign%
NEXT student%

placing AID and UID in the SlaveAssignmentType UDT may even be superfluous since it's already carried by the dimensional elements.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#7
Looking at your data format, here's how I'd read and write that data to keep it simple and efficient.

1)Determine the MAX number of students that a class would ever hold, then round up to the nearest 10s.  (For 23 students, round to 30, for example.)
2)Since text files are tiny and hard drives are huge, DOUBLE that number for "future proofing" your database.  (That 23 just became 60.)

Now that you have a set number of elements to work with, take a close look at your data.  What I'd do is store my data in two arrays, based off the same index -- StudentName(100) As String * 100 and Grades(100,100) AS SINGLE.  Basically:
Dim StudentName(100) As String * 100
Dim Grades(100,100) AS SINGLE

Now I can use one binary file to hold all my data in, and I can access any part of it instantly.
Write StudentName() to the file first, as a header.
Write Grades() to the file next.

Depending on how you index that Grades array, your students grades will each be placed left to right or from top to bottom, but either way they'll be in a sequential order.

Want Ami Li's test result for her third test?  It's in that file at position (100 * 100 for the name header = 10000) + 400 * 1st Index + 4 * 2nd Index (based off Grades (x, y) <-- x and y are your indexes).

A database much larger than you currently need for future proofing, that offers instant access to any cell of information which you want.  What could be better than that?
Reply
#8
There is an easy way to store 20 tests or however many maximum amount AND use it in an UDT AND store the UDT into a file!

Just setup a Student Tests String 3 times maximum of possible given tests (Numbered 1,2,3... like used in array)
With 3 characters reserved for each test, you can have scores from 0 to 999 but mostly 0 to 100 maybe extra credit on 100? it's available.

I have prepared a couple very simple routines for storing test scores into the Students Tests String that can be a fixed string of 60 characters for maximum 20 tests example.
Code: (Select All)
Dim studentTest3X20 As String * 60 ' fit 20 tests   into fixed string that can be stored from UDT

Data 100,82,75,98,66
For i = 1 To 5 ' test PutTest loading the student test string with 5 tests
    Read testscore
    PutTest studentTest3X20, i, testscore
Next

' ok read back scores  in reverse order
For i = 5 To 1 Step -1
    Print GetTestScore(studentTest3X20, i)
Next


Sub PutTest (studentTest$, testNumber, testScore)
    Mid$(studentTest$, testNumber * 3 - 2, 3) = Right$("   " + _Trim$(Str$(testScore)), 3)
End Sub
Function GetTestScore$ (studentTest$, testNumber)
    GetTestScore$ = Mid$(studentTest$, testNumber * 3 - 2, 3)
End Function

Same approach can be taken for Assignments using more data strings for UDT and adding another parameter to Get and Put functions with string width of each data item.
b = b + ...
Reply
#9
@NasaCow here is a sample Student UDT that can hold scores to 20 tests and do 20 Projects details with updated subs and functions to store array data into a Fixed string that can be saved to file because all UDT data is fixed size ie, no variable length strings.
Code: (Select All)
Type NameListType 'Used for the student name database
    PinYinName As String * 20
    FirstName As String * 20
    MiddleName As String * 20
    LastName As String * 20
    Year As Integer
    Month As Integer
    Day As Integer
    HouseColor As String * 8
    MomName As String * 30
    MomPhone As String * 20 'Saved as string to support symbols and international prefixes
    MomEmail As String * 38
    DadName As String * 30
    DadPhone As String * 20
    DadEmail As String * 38
    'UID As Integer ' still need??    Don't think so because tests and projects stored with eacg student
    ' But do have ProjectCode for connecting details of each project assigned
    Tests As String * 60 ' 20 tests 3 chars per score
    ProjectCodeID As String * 60 ' 20 codes at 3 chars per code this could hook up to the Project Details
    ProjectPts As String * 60 ' 0 to 999 points per project allows max 20 projects
    ProjectFlags As String * 60 ' 20 flag codes up to 3 digits each
    ProjectFlags2 As String * 60 ' 20 more flag codes ???
    ProjectNotes As String * 10240 ' thats 512 per comment, allows 20 comments for each of 20 projects

End Type


' test revised sub and function Put3 and Get3$
Dim studentTest3X20 As String * 60 ' fit 20 tests   into fixed string that can be stored from UDT

Data 100,82,75,98,66
For i = 1 To 5 ' test PutTest loading the student test string with 5 tests
    Read testscore
    Put3 studentTest3X20, i, testscore
Next

' ok read back scores  in reverse order
For i = 5 To 1 Step -1
    Print Get3$(studentTest3X20, i)
Next



' 5 types above put 3 digit integers into a string that is holding data like an array
Sub Put3 (DataString As String * 60, Index As Long, IntItem As Integer) ' store 3 digits integers into a string of 20
    Mid$(DataString, Index * 3 - 2, 3) = Right$("   " + _Trim$(Str$(IntItem)), 3)
End Sub

Function Get3$ (DataString As String * 60, Index As Long)
    Get3$ = Mid$(DataString, Index * 3 - 2, 3)
End Function

' For space hog comments
Sub PutProjectNote (DataString As String * 10240, Index As Long, Note As String * 512) ' store 512 note into big string
    Mid$(DataString, Index * 512 - 511, 512) = Note
End Sub

Function GetProjectNote$ (DataString As String * 10240, Index As Long)
    GetProjectNote$ = Mid$(DataString, Index * 512 - 511, 512)
End Function

So you can store the students tests and project details with each Student File and the details of each project in another file and use a Project code number to connect the student data on project to details of project.
b = b + ...
Reply
#10
(02-16-2023, 04:25 PM)bplus Wrote: @NasaCow here is a sample Student UDT that can hold scores to 20 tests and do 20 Projects details with updated subs and functions to store array data into a Fixed string that can be saved to file because all UDT data is fixed size ie, no variable length strings.
Code: (Select All)
Type NameListType 'Used for the student name database
    PinYinName As String * 20
    FirstName As String * 20
    MiddleName As String * 20
    LastName As String * 20
    Year As Integer
    Month As Integer
    Day As Integer
    HouseColor As String * 8
    MomName As String * 30
    MomPhone As String * 20 'Saved as string to support symbols and international prefixes
    MomEmail As String * 38
    DadName As String * 30
    DadPhone As String * 20
    DadEmail As String * 38
    'UID As Integer ' still need??    Don't think so because tests and projects stored with eacg student
    ' But do have ProjectCode for connecting details of each project assigned
    Tests As String * 60 ' 20 tests 3 chars per score
    ProjectCodeID As String * 60 ' 20 codes at 3 chars per code this could hook up to the Project Details
    ProjectPts As String * 60 ' 0 to 999 points per project allows max 20 projects
    ProjectFlags As String * 60 ' 20 flag codes up to 3 digits each
    ProjectFlags2 As String * 60 ' 20 more flag codes ???
    ProjectNotes As String * 10240 ' thats 512 per comment, allows 20 comments for each of 20 projects

End Type


' test revised sub and function Put3 and Get3$
Dim studentTest3X20 As String * 60 ' fit 20 tests   into fixed string that can be stored from UDT

Data 100,82,75,98,66
For i = 1 To 5 ' test PutTest loading the student test string with 5 tests
    Read testscore
    Put3 studentTest3X20, i, testscore
Next

' ok read back scores  in reverse order
For i = 5 To 1 Step -1
    Print Get3$(studentTest3X20, i)
Next



' 5 types above put 3 digit integers into a string that is holding data like an array
Sub Put3 (DataString As String * 60, Index As Long, IntItem As Integer) ' store 3 digits integers into a string of 20
    Mid$(DataString, Index * 3 - 2, 3) = Right$("   " + _Trim$(Str$(IntItem)), 3)
End Sub

Function Get3$ (DataString As String * 60, Index As Long)
    Get3$ = Mid$(DataString, Index * 3 - 2, 3)
End Function

' For space hog comments
Sub PutProjectNote (DataString As String * 10240, Index As Long, Note As String * 512) ' store 512 note into big string
    Mid$(DataString, Index * 512 - 511, 512) = Note
End Sub

Function GetProjectNote$ (DataString As String * 10240, Index As Long)
    GetProjectNote$ = Mid$(DataString, Index * 512 - 511, 512)
End Function

So you can store the students tests and project details with each Student File and the details of each project in another file and use a Project code number to connect the student data on project to details of project.

This is an interesting way of doing it. It is old school for sure to save space. I know if I actually PLANNED AHEAD instead of, you know, just code without much forethought, I would had not have been in this mess!

Thanks everyone for the ideas and suggestions, I am going to keep plowing ahead and see what I can get made  Big Grin If any of you are familar with PowerSchool's gradebook, you might know where I am going with this  Cool
Reply




Users browsing this thread: 9 Guest(s)