Query to assign values to a cost item based on dates from a contract (1 Viewer)

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Hello all,

I have been working my head to create a query that will populate a contract number to a specific cost item based on: Contract Validity, type of cost and Location.
Given that the contracts might be for several types of costs, there has to be a separate table that assigns the type of costs to each contract.

See example below, the ultimate goal is to populate the Contract Number (yellow highlight) on the Cost Item Table based on the 2 first tables: Contract List and Contract Assignment.

Thanks for your help!
 

Attachments

  • Contract List.JPG
    Contract List.JPG
    24.6 KB · Views: 93
  • Contract Assignment.JPG
    Contract Assignment.JPG
    24.2 KB · Views: 96
  • Cost Items.JPG
    Cost Items.JPG
    31.2 KB · Views: 96

JHB

Have been here a while
Local time
Today, 12:30
Joined
Jun 17, 2012
Messages
7,732
..
the ultimate goal is to populate the Contract Number (yellow highlight) on the Cost Item Table based on the 2 first tables: Contract List and Contract Assignment.

Thanks for your help!
And what problem do you've with that?
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
use an Update Query against Cost Items table:

Update [Cost Items] AS T1 INNER JOIN [Contract Assignment] AS T2
ON T1.[CostType]=T2.[ContractType] AND T1.[Location]=T2.[Location]
SET T1.[ContractNumber]=T2.[ContractNumber];

OR

UPDATE [Cost Items], [Contract Assigment]
SET [Cost Items].[ContractNumber]=[Contract Assignment].[ContractNumber]
Where
[Contract Assignment].[Contract Type]=[Cost Items].[CostType] AND
[Contract Assignment].[Location]=[Cost Items].[Location]
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Dear arnelgp,

That works marvellous! thank you for your help!

I will try it and let you know if any issues.

thanks,
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Dear arnelgp,

Well, I thought it was working ok but there is no reference to the validity that is on the [Contract List].

I would need this query to also reference to the "ValidFrom" and "ValidTo" dates on the [Contract List] in order to properly update it.

Thanks again!
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
revised our query to include Contract List.

UPDATE ([COST ITEMS] INNER JOIN [CONTRACT ASSIGNMENT] ON ([COST ITEMS].LOCATION = [CONTRACT ASSIGNMENT].LOCATION) AND ([COST ITEMS].COSTTYPE = [CONTRACT ASSIGNMENT].CONTRACTTYPE)) INNER JOIN [Contract List] ON [CONTRACT ASSIGNMENT].CONTRACTNUMBER = [Contract List].CONTRACTNUMBER SET [COST ITEMS].CONTRACTNUMBER = [CONTRACT ASSIGNMENT].[CONTRACTNUMBER]
WHERE ((([COST ITEMS].COSTDATE) Between [Contract List].[VALIDFROM] And [Contract List].[VALIDTO]));
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
That's excellent, thank you again.

Now one last thing, sometimes for the current contracts, the "ValidTo" date will be BLANK... is there a way to default blank ones to today's date on the query (Not on the table) so that it also updates them properly.

Thanks!
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
just change this in the query:

Between [Contract List]!ValidFrom] And ...

to:

Between IIF(IsNull([Contract List]!ValidFrom]), Date, [Contract List]!ValidFrom]) And ...
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Hi

I am getting a syntax error with the following:

UPDATE ([COST ITEMS] INNER JOIN [CONTRACT ASSIGNMENT] ON ([COST ITEMS].LOCATION = [CONTRACT ASSIGNMENT].LOCATION) AND ([COST ITEMS].COSTTYPE = [CONTRACT ASSIGNMENT].CONTRACTTYPE)) INNER JOIN [Contract List] ON [CONTRACT ASSIGNMENT].CONTRACTNUMBER = [Contract List].CONTRACTNUMBER SET [COST ITEMS].CONTRACTNUMBER = [CONTRACT ASSIGNMENT].[CONTRACTNUMBER]
WHERE ((([COST ITEMS].COSTDATE) Between IIF(IsNull([Contract List]!ValidFrom]), Date, [Contract List]!ValidFrom]) And [Contract List].[VALIDTO]))

Furthermore, shouldn't the IIF function refer to the ValidTo i/o ValidFrom??

thanks!
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
Sorry, i missed two left sqr bracket at ValidFrom. And use the expression to ValidTo.
 

isladogs

MVP / VIP
Local time
Today, 11:30
Joined
Jan 14, 2017
Messages
18,209
The IIf Part of Arnel's code correctly referred to ValidFrom.

If you changed the iif code the query would be between validTo and ValidTo!

Just add the 2 missing [ brackets as mentioned in the last post.
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Dear all, thank you for the quick responses

Seems to be working, will contact you if any issues.

Best regards
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 06:30
Joined
Feb 19, 2002
Messages
43,223
You seem to have an answer but I question the process. It doesn't make sense to me that you would be doing this with an update query. You should have tables that define contract types, locations and contracts.

The contract data entry form should have a subform where you can select combinations of types and locations and as the row is entered, Access will automatially assign the contract number for the contract on the main form. No code or action queries should be required.
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Dear Pat,

Thanks, I have considered this, as a matter of fact take a look the image for the relationship and how I planned to relate the tables.

The issue lies that I upload the database for the Cost Items and most of them do not have a contract yet hence those items will normally be omitted.

I have thought about creating a "Pending" contract number so that when I upload these cost items, the ones with no contract will have a contract number like "pending001".

Now, once a there is contract that covers that specific Cost Item, what query could I use to change the "pending001" to the contract to the correct Contract number?

This is how far I got:

UPDATE [Contract List] INNER JOIN [Contract Assignment] ON [Contract List].ContractNumber = [Contract Assignment].ContractNumber SET [Contract Assignment].ContractNumber = [Contract List].[ContractNumber];


Thanks again!
 

Attachments

  • Relationship.JPG
    Relationship.JPG
    42 KB · Views: 102
Last edited:

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Dear all,

I have found a way utilizing Arnel's query and creating a 2nd one that updates the Assignment ID on the Cost Items table, this way the cost items are linked to the Contract Assignment table.

Dear Arnel,

I need 2 last tweaks to your query (Shown at the bottom):

1) Match the VendorID on the Cost Items table to the VendorID on the Contract List Table as a contract could exist for the same location and for the same cost type but for 2 different Vendors.

2) Would like the option to leave the Location on the Contract Assignment table blank for some contracts, if this is the case then the match of the query would be done solely on the VendorID and the CostType. If a Location does exist then limit the query to update it accordingly.

Thanks!

UPDATE ([COST ITEMS] INNER JOIN [CONTRACT ASSIGNMENT]

ON ([COST ITEMS].LOCATION = [CONTRACT ASSIGNMENT].LOCATION)

AND ([COST ITEMS].COSTTYPE = [CONTRACT ASSIGNMENT].CONTRACTTYPE)) INNER JOIN [Contract List]

ON [CONTRACT ASSIGNMENT].CONTRACTNUMBER = [Contract List].CONTRACTNUMBER

SET [COST ITEMS].CONTRACTNUMBER = [CONTRACT ASSIGNMENT].[CONTRACTNUMBER]

WHERE (([COST ITEMS].COSTDATE) Between [Contract List].[ValidFrom] And IIF(IsNull([Contract List]![ValidTo]), date,[Contract List]![ValidTo]));
 

Attachments

  • Relationship.JPG
    Relationship.JPG
    42 KB · Views: 73

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
sorry for long response.
you have too many criteria and am afraid
i can't do it. it will be unfair for other
so please address it to Everyone.

i am moving away from SQL, instead will
use VBA. haven't really fully tested it.
if not working, tell me.

paste the code in a Module"

Code:
Public Function fnContractNum(dDate As Variant, ctype As Variant, location As Variant, vendor As Variant) As Variant
    Dim DB As DAO.Database
    Dim RS As DAO.Recordset
    Dim str As String
    dDate = CDate(dDate)
    
    Set DB = CurrentDb
    Set RS = DB.OpenRecordset("SELECT ContractNumber From [Contract List] Where " & _
                    "#" & Format(dDate, "mm/dd/yyyy") & "# Between " & _
                    "ValidFrom And Nz(ValidTo, #" & _
                    Format(DateSerial(Year(Date) + 1, 12, 31), "mm/dd/yyyy") & "#) And " & _
                    "VendorID = " & FixUp(vendor), _
                    dbOpenSnapshot)
    If RS.RecordCount = 1 Then
        fnContractNum = RS(0)
    Else
        If RS.RecordCount > 0 Then
            With RS
                .MoveFirst
                While Not .EOF
                    str = str & !contractnumber & ","
                    .MoveNext
                Wend
                str = Left(str, Len(str) - 1)
                .Close
            End With
            Set RS = DB.OpenRecordset("select ContractNumber, Location from [Contract Assignment] Where " & _
                "ContractNumber IN (" & str & ");", dbOpenSnapshot)
            With RS
                If Not (.BOF And .EOF) Then
                    .MoveFirst
                    Do While Not .EOF
                        If Trim(!location & "") = location & "" Then
                            fnContractNum = !contractnumber
                            Exit Do
                        End If
                    Loop
                End If
                .Close
            End With
        End If
    End If
    Set RS = Nothing
End Function


Public Function FixUp(ByVal varvalue As Variant) As Variant

    ' eTutorials.org
    ' SQLQuote
    ' Add appropriate delimiters, depending on the datatype.
    ' Put quotes around text, #s around date, and nothing
    ' around numeric values.
    'Const QUOTE As String = Chr$(34)
    Dim QUOTE As String
    QUOTE = Chr$(34)
    
    Select Case VarType(varvalue)
        Case vbInteger, vbSingle, vbDouble, vbLong, vbCurrency, vbBoolean, vbByte
            FixUp = CStr("0" & varvalue)
        
        Case vbString
            FixUp = QUOTE & varvalue & QUOTE
            
        Case vbDate
            FixUp = "#" & Format(varvalue, "mm/dd/yyyy") & "#"
            
        Case Else
            FixUp = "Null"
    End Select
End Function

the create a query:

UPDATE [cost items] SET [cost items].contractnumber = fnContractNum([costdate],[costtype],[location],[vendorid]);
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Hello,

The module created, does it need any specific name?

I have tried it and it does not work.
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 18:30
Joined
May 7, 2009
Messages
19,233
Give me something to work on, put it on a zip.
 

fedebrin

Registered User.
Local time
Today, 03:30
Joined
Sep 20, 2017
Messages
59
Hello Arnel,

I tried actually a simpler way. I added extra fields to the "Contract Assignment" like VendorID and the dates, then I used a combination of queries:

1) fill out the new fields in the "Contract Assignment"
2) with this information complete a query that will match the ContractNumber to the "Cost Items" table taking in consideration the VendorID and the CostType - note I am not taking in consideration the Location yet.
3) the same as above but on this third one the location is taken in consideration

So far it is working well, will let you know if any further issues.

Thanks!
 

Users who are viewing this thread

Top Bottom