Results 1 to 15 of 15
  1. #1
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6

    Copy field with multiplle delimited entries into related table rows

    Greetings,



    I am using a MS Access 2010 form to interface with some SQL-linked tables.

    Table1 contains a PatientID (primary key) and a field named TestIDs. Currently the TestIDs field holds a list of multiple test IDs for each record within the TestIDs field. Each test id listed within this TestIDs field is separated by a semicolon. Thus the contents of a typical record from table 1 would look like this:
    PatientID = 100 (primary key)
    TestIDs: 123;45;612;2 (text or varchar field)

    Table2 contains the description data for each individual testID:
    TestsID (number field and primary key)
    TestName (text or varchar field)

    My goal is to present the combined info on my form (show patient name with a list of TestIDs and their associated Test Names)


    My initial thoughts:
    I am thinking that in order to bring this together and turn this into a truly relational database here, that I most somehow 1st run a query or code on the access side that somehow would take the delimited contents of the TestIDs field from table1 (remember, a single record for the TestIDs field from Table1 will contain contents that include multiple test IDs and will look like this: 123;45;612;2), and somhow copy them into new table (table 3) that would contain individual rows for patientID, TestID

    Thus, I would turn this:
    table1
    PatientID TestIDs
    1 123;45;612;2


    into this:

    table3
    PatientID TestID
    1 123
    1 45
    1 612
    1 2



    I could then use table 3 to pull in the name from table 2, and thus display whatever I need on my form, etc.

    Am I on the right track?

    Presuming that I have an empty table (table3) with PatientID and TestID, How would I use the MS Access front end to copy the contents as described.
    What kind of append query or code would let me transform the contents from a single field in table1 to individual rows in table3?
    What's tthe best way to do this?


    As time goes on and more records are added in Table1 (in the same way) I'll need to normalize the data here on an ongoing basis (figure some code and/or append queries can be running in the background when adding or modifying a record to to normalize data as changes are made, etc )


    Thanks for all your help!!!!!

  2. #2
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    What field will you use to join Table3 to Table2?
    Will it be 'TestID' from Table3 and 'TestsID' from Table2?

  3. #3
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6
    Thanks for your response. I plan on using the PatientID field in in table1 to then join to the PatientID field in table3 to provide the basic relationship between patients and the individual tests. However, since I still want to see the test name too (and since table 3 doesn't hold the test name), I would then have to join table3 to table2 by using the TestID field to link them.

    Left inner join Table1 to Table3 on the PatientID field (lists all patients table1 with matching tests in table3)
    then
    Left Inner join from Table3 to Table2 using the TestID field so that I can display the test name instead of just the test ID number


    Thanks again!!!

  4. #4
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    Are you experienced writing code?
    If so, have you used function-calls from a field in a query?
    For your ';' delimited values in that one field, is there a known maximum number of values the field can have.
    I mean - do you know how many ;-delimited values there CAN be in that one field?

    Here's what I'm thinking:
    1. You can use some form of the IIf statement below in a query field to return one of your values.
    This is a field I have in a Test Query that returns:
    a. the entire field if there is no "/" in the string
    b. everything to the left of the "/" if there IS one in the string.
    Code:
    Search_String: IIf(InStr(1,[Test],"/")=0,[Test],Left([Test],(InStr(1,[Test],"/")-1)))
    2. You can send a call to a function from the field in your query and pass the entire field to the function and perhaps a number indicating which value [the first, second, third . . .] you want.
    So - if your field is calling the function for the 1st value:
    The function will the entire string, look for the 1st instance of ";" and return everything to the left of it - to give you the 1st value.
    If your field is calling the function for the 2nd value:
    The function will the entire string, look for the 2nd instance of ";" and return everything to the left of it - to give you the 2nd value.
    . . . and so on.

    If you don't know the maximum number of values that one field may hold . . . then you'll have to use the function to determine how many values are in the field by 'counting' the number of instances of ";" . . .

    Let me know if this gives you something to start with or if you need more help.

  5. #5
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6
    Thank You. What you say makes sense. The number of delimited values in that field could vary =greatly.... could be one or two but then could also be 50 or 60 for some). I am limited in code skills unfortunately (I am familiar with the IIF, and some of the simpler VB statements but, I have not tried to create a function yet),. I do understand the logic of what you are saying (as far as Nitti gritty in building the function statement, not so much.... a skill this experience will hopefully let me begin to acquire. I am going to jump in and give it try. Thanks for pointing me in the right direction

  6. #6
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    Can you ask your users to stop putting multiple values in one cell?

  7. #7
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    I'll try & work up a function that deals with doing what I talked about.
    I'll let you know when it is done and I'll post the code and explanation here.
    It won't be real quick - but i'll be working on it.

  8. #8
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    What are the Data Types for PatientID, and TestIDs in Table1?
    Are they both Number?

  9. #9
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6
    Thanks for your help with this. I appreciate it very much!!
    Table1: PatientID is a numeric field (it is an INT field in the source SQL table)
    Table1: TestIDs is a text field (in the source SQL field it is a varchar field)

    The reason the field has so many delimted test IDS, is that it's simply a copy/paste from a business objects query criteria (the criteria in the query contains all of these test codes. Thus, the user is simply coopyiong them and then pasting them into the database field for TestIDs (user's are not hand typing them in this way or anything).

    Thanks again for your assistance!!!!

  10. #10
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    I guessed that TestIDs had to be Text - because it uses the ";" . . . that was a stupid question on my part!
    Yesterday I got as far as creating a loop to get at each successive ";" in the cell - and show each additional TestID.
    I was not able to isolate each of the values before I shut down for the day.

    Today I'll work on getting each successive TestID paired with the PatientID and entered into the third Table.
    I'll let you know when it's done - or if I have questions.
    If I don't get too busy here at work, I may be able to have something for you today.

  11. #11
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6
    I am grateful for your efforts! Amazing ! I don't even see modules anymore in MS Access2010 (we just moved from 2003 to 2010 at our organization... the interface for this part must have changed greatly). I am eager to implement this and at the same time learn more about implementing a function in MS Access 2010 (thanks to you).

  12. #12
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    The Modules are available in 2010.
    You know where you see your Tables and Queries & reports etc?
    Well - drop the arrow down at the top of that section and select 'Object Type' and 'All Access Objects'.
    Now - if you have a Module in your database - it will show uner Modules.
    For what I'm doing - you'll probably have to create a Module anyway [Create -> Module].

    I've been busy today - so I haven't got your code finished. I'm struggling with the logic on reading the 3rd and 4th values . . . I'm getting a ";" along with part of the values - so it's all about how I'm manipulating the Position markers in the code . . .

  13. #13
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    Here it is.

    Create a new module if you don't already have one.
    Type in Option Explicit.
    Paste this code in.

    I am reading from 'Table5' and writing to 'Table5_Write'.
    In Table5_Write - PatientID must not be a Primary Key.
    Make sure your Table names match what you have in your Database.
    [table1 & table3?]

    Highlight the first row -
    Function Function Split_Field_Values()
    Hit the run button or press F5.
    You should have what you need.

    Please test to make sure it is performing to expectation.
    I hope this gives you a starting point to using VBA.

    Code:
    Function Split_Field_Values()
    'This function splits each row with multiple ";" - delimited values in one field
    '. . . into multiple rows with one of the values in each row
    '. . . and writes the rows to a 'receiving' Table [Table5_Write].
    
    'Table5 contains rows which have Multiple values in the TestID field
    'Each row has a PK PatientID field.
    'Table5_Write has a PatiendID [cannot be Primary Key] and a TestID field.
     
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
     
    Dim strField1, strField2, strNewField1, strNewField2, strSQL As String
    Dim intPos, intPos2, intCount, intLength As Integer
    Dim Found As Boolean
    On Error GoTo Error_Handle
    DoCmd.SetWarnings False
     
    Set db = CurrentDb
    strSQL = "Select * From [Table5] ORDER  BY [PatientID]"
    Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
    With rs
    'This loop goes through all the records in strSQL - one by one.
    Do While Not rs.EOF
        
        'Set intPos = 1 because we are now at a new row in the recordset.
        intPos = 1
        intCount = 1
        
        'Get the values from the current row.
        strField1 = rs![PatientID]
        strField2 = rs![TestID]
         
        'Get the first value.
        If InStr(intPos, strField2, ";") > 0 Then               ' ";" found.
            Found = True
            strNewField2 = Left(strField2, (InStr(intPos, strField2, ";") - 1))
            
            strSQL = "INSERT INTO Table5_Write (PatientID, TestID) "
            strSQL = strSQL & "VALUES (" & strField1 & "," & "'" & strNewField2 & "'" & "); "
            
            'Execute Insert SQL.
            DoCmd.RunSQL strSQL
        
        Else                                                    ' ";" not found.
            Found = False
            If Len(strField2) > 0 Then                          ' the field is not empty.
                strNewField2 = strField2
        
                strSQL = "INSERT INTO Table5_Write (PatientID, TestID) "
                strSQL = strSQL & "VALUES (" & strField1 & "," & "'" & strNewField2 & "'" & "); "
                
                'Execute Insert SQL.
                DoCmd.RunSQL strSQL
            Else                                                ' the field is empty.
                'Not sure if you'll ever have a PatientID with no TestIDs in it . . .
                'Just leaving a place holder here in case you need to code.
                
            End If
        End If
         
        'Get new start position [intPos].
        intPos = InStr(intPos, strField2, ";") + 1
        
        If Not (Found) Then        'There is no ";" in this row - single value already written.
            'Do nothing
        
        Else                       'A ";" was found - keep going.
        
        'This Do While Loop keeps searching strField2 of the current row of data till there are no more instances of ";"
        Do While intPos > 0
        
             intPos2 = 0
             intPos2 = InStr(intPos + 1, strField2, ";")
             intLength = (intPos2 - intPos)
             
            If intLength > 0 Then
                'Get subsequent values from the TestID string.
                strNewField2 = Mid(strField2, intPos, intLength)
                
                'Write row with last of the delimited values here.
                'Create SQL for Last Row of data that is still stored even though Access found the EOF.
                strSQL = "INSERT INTO Table5_Write (PatientID, TestID) "
                strSQL = strSQL & "VALUES (" & strField1 & "," & "'" & strNewField2 & "'" & "); "
                'Execute Insert SQL.
                DoCmd.RunSQL strSQL
                 
            Else
            'The Instr function returned a 0 - no more ";" found = last value in field.
            'Write everything to the right of the last ";".
                strNewField2 = Right(strField2, (Len(strField2) - (intPos - 1)))
                'Write row with last of the delimited values here.
                'Create SQL for Last Row of data that is still stored even though Access found the EOF.
                strSQL = "INSERT INTO Table5_Write (PatientID, TestID) "
                strSQL = strSQL & "VALUES (" & strField1 & "," & "'" & strNewField2 & "'" & "); "
                'Execute Insert SQL.
                DoCmd.RunSQL strSQL
                 
                'Since we are at the last value in field - Get out of this Loop
                'without incrementing intPos.
                'I know this is not the most elegant way out of this . . .
                Exit Do
             End If
            
            'Set intPos to the last ";" encountered [intPos2].
            intPos = intPos2 + 1
            intCount = intCount + 1
            
        Loop
        End If
        
    .MoveNext                               'Move to next record in recordset.
    Loop                                    'Back to 'Do While' to check if we are at the end of the recordset.
     
    Exit_Split_Field_Values:
        If Not rs Is Nothing Then
            rs.Close
            Set rs = Nothing
        End If
        Set db = Nothing
        DoCmd.SetWarnings True
        Exit Function
        
    Error_Handle:
        MsgBox Err & " " & Error$
        Resume Exit_Split_Field_Values:
    End With
    End Function
    Let me know how it goes.
    Mark the thread 'Solved' if it resolves your issue.

  14. #14
    davedvf is offline Novice
    Windows 7 32bit Access 2010 32bit
    Join Date
    Feb 2012
    Posts
    6
    Fantastic. I will be working with this code this evening and let you know (never expected to receive this much help). Thanks so much for your willingness to do this!!!!

  15. #15
    Robeen is offline VIP
    Windows XP Access 2010 32bit
    Join Date
    Mar 2011
    Location
    Tulsa, Oklahoma.
    Posts
    1,596
    Let me know how it goes!

Please reply to this thread with any new information or opinions.

Similar Threads

  1. Copy paste multiple rows in a table
    By Biologybook in forum Access
    Replies: 9
    Last Post: 04-07-2014, 02:08 PM
  2. Replies: 5
    Last Post: 02-21-2012, 07:33 AM
  3. Parsing A Comma Delimited Field
    By AccessGeek in forum Import/Export Data
    Replies: 6
    Last Post: 02-03-2011, 01:52 PM
  4. String to Copy a Field of Data to Another Table
    By aquarius in forum Programming
    Replies: 1
    Last Post: 09-17-2010, 09:02 AM
  5. Copy form field to another table
    By Dega in forum Forms
    Replies: 6
    Last Post: 05-21-2010, 02:57 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums