VBA - Validate quantity including the field being edited - sql-server

Setup: MS Access + SQL Server 2019.
I have Purchase Orders which have to be Delivered. For example:
PurchaseOrderDetailID
QtyOrdered
1
10
DeliveryID
DateShipped
DateReceived
1
1.1.2022
2.1.2022
2
1.2.2022
2.2.2022
DeliveryDetailID
DeliveryID
PurchaseOrderDetailID
QtyDelivered
1
1
1
5
2
2
1
3
This means that there are 10 items ordered, 5 items have been delivered in the first Delivery, 3 items in the second one, therefore 8 delivered in total.
Meaning that this Purchase Order is partially delivered at the moment.
I have a Delivery Data Entry Form in MS Access (back end is SQL Server). I want to validate the quantity so that TotalQtyDelivered cannot be more than TotalQtyOrdered.
Private Sub txtQuantity_BeforeUpdate(Cancel As Integer)
Dim QtyOrdered, QtyDelivered, LeftToDeliver As Double
QtyOrdered = DLookup("QtyOrdered", "dbo_v_PurchaseOrderItemStatus", "PurchaseOrderDetailID=" & Me.PurchaseOrderDetailID)
QtyDelivered = DLookup("QtyDelivered", "dbo_v_PurchaseOrderItemStatus", "PurchaseOrderDetailID=" & Me.PurchaseOrderDetailID)
LeftToDeliver = QtyOrdered - QtyDelivered
If Me.txtQuantity > LeftToDeliver Then
MsgBox "TOO MUCH"
Me.Undo
Cancel = True
End If
End Sub
This works fine if I'm entering a new Delivery. But if I am editing an existing delivery, the algorithm accounts also for the previous value in the Qty field.
With the example above:
QtyOrdered = 10
QtyDelivered = 8
(this is calculated by SQL View)
Let's say that I made a mistake and there were actually 4 items delivered in the second delivery, istead of 3. When I try to change the value, this happens:
Me.txtQuantity = 4
LeftToDeliver = 2
(because it still accounts for the "3" previously inserted in Me.txtQuantity
Result: Operation failed, too many items. However in reality there should only be 9 items.
Can you please advise how I should do this correctly? Thanks.

Related

SQL: Trying to find if gift was given year following first gift year

I'm using SSMS version 18.9.2 and I'm trying to get a list IDs who gave a gift the year following the year after their FIRST gift date. Meaning if their first gift was in 2019 and they gave a gift in 2020 then row count = 1, then the next person's first gift also was in 2019, but did NOT give a gift in 2020, then row count would remain 1 even though we have reviewed a total of two people. Hope that makes since.
Using a sample data as this, I would expect my row count to be 1; returning only ID 2
ID
Date
1
3/8/1981
1
2/11/1988
1
2/15/1995
2
2/22/1982
2
2/24/1983
2
3/15/1983
2
2/17/1984
3
2/16/1984
3
3/13/1984
3
6/13/1986
4
2/2/1983
4
3/11/1985
4
3/21/1986
This is the closest I've gotten to work. Notice the two different HAVINGs where as first works but the second fails which the second is how it needs to work:
SELECT DISTINCT
gifts1.giftid,
YEAR(gifts2.gifteffdat) AS 'MINYR',
YEAR(MIN(gifts1.gifteffdat)) AS 'MINYR+1'
FROM
gifts AS gifts1
INNER JOIN
gifts AS gifts2 ON gifts1.giftid = gifts2.giftid
AND DATEDIFF(year, gifts2.gifteffdat, gifts1.gifteffdat) = 1
GROUP BY
gifts1.giftid, gifts1.gifteffdat, gifts2.gifteffdat
-- THIS HAVING WORKS
HAVING
(YEAR(gifts2.gifteffdat) = 1982)
-- THIS HAVING DOESNT WORK
-- HAVING YEAR(gifts2.gifteffdat) = YEAR(MIN(gifts1.gifteffdat)) +1
I appreciate any help! Thank you!

Arrayformula with vlookup - Range Issue

I am trying to range the Data from the tab "Extracted data" in the tab "Action Items"
Conversion Potential column (Action items tab) is taking the data from CTR Delta (Extracted data tab).
Relevance column (Action items tab) is taking the data from Position Delta (Extracted data tab).
For some reasons, it simply does not range the data in the right way.
Conversion Potential Range should go like:
CTR Range
-2 1
-1 2
0 3
1 4
2 5
Relevance is expected to be ranged like:
Range Result
0-10 5
10-20 4
20-30 3
30-40 2
40-50 1
50-100 0
https://docs.google.com/spreadsheets/d/1MlyMmZ3JcWmYeDS86YB7yQnTsb7Fv0btYa7b4o-zwgo/edit#gid=1011640328
For 'Action Items'!M3 (delete cells below):
=arrayformula({"Conversion Potential";iferror(vlookup(vlookup(D4:D,'Extracted Data'!A:N,14,0),{-2,1;-1,2;0,3;1,4;2,5},2,1),)})
For 'Action Items'!N3 (delete cells below):
=arrayformula({"Relevance";iferror(vlookup(vlookup(D4:D,'Extracted Data'!A:N,13,0),{0,5;11,4;21,3;31,2;41,1;51,0},2,1),)})

How to make Google Studio Handle Blank values in my source (google sheet) when creating calculated fields

I'm trying to create a field in Google Data Studio that would sum 5 different fields (my source), the problem is those values are currently blank (the sheet is reading from another system), but i want to create the field anyway for when the values are feeded in. Google Data Studio is telling me the field cannot be deleted
I've tried to handle with CASE if X is null then 0... but this isnt working, when i try to manualy add data into the sheet (the source) it works, but then when i delete it the scorecard i'm using is returning error
This is the code for one of the 5 fields i'm trying create.
The 1 to 5 range is the range of all possible values in the spreadsheet.
Field A:
case
when X IS NULL then 0
when X = 1 then 1
when X = 2 then 2
when X = 3 then 3
when X = 4 then 4
when X = 5 then 5
else 0
end
Failed to create field. Please try again later... this is when i try to create the field when the values of the fields in the spreadsheet are blanks.
0) Summary
IFNULL (#1) is the new recommended suggestion; NARY_MAX (#2) was the original suggestion:
1) Update - Recommend Suggestion (IFNULL)
The 01 Apr 2021 Update introduced the IFNULL function which is specifically designed to assign a numeric value to NULL values, whereas the original NARY_MAX Calculated Field below would set the minimum value to 0 which would lead that negative values (such as -1) being be captured as a 0:
IFNULL(Field1, 0) +
IFNULL(Field2, 0) +
IFNULL(Field3, 0) +
IFNULL(Field4, 0) +
IFNULL(Field5, 0)
Added a New Page to the Editable Google Data Studio Report (Embedded Google Sheets Data Source) and a GIF to elaborate:
2) Original Suggestion (NARY_MAX)
It can be achieved using the NARY_MAX function:
NARY_MAX(Field1, 0) + NARY_MAX(Field2, 0) + NARY_MAX(Field3, 0) + NARY_MAX(Field4, 0) + NARY_MAX(Field5, 0)
How it works:
NARY_MAX takes the MAX value from a range of fields, thus in the above case, when evaluating NARY_MAX(NULL, 0), 0 is greater than NULL, thus 0 is preferred in the calculation.
NULL vs 0
While a number has a value (negative, 0 or positive), NULL is not a value, thus can't be used in a calculation.
Google Data Studio Report to demonstrate:

Adding CR/DR to accounting transactions

I have 7 tables of COA as show in the picture attached. what I need is whenever opening balance goto - (negative) , the type must automatically show CR sign and whenever that account go to positive, it must change to DR automatically. The account will change to DR or CR as per entries. Suppose I am doing entry in cash payment and if cash in hand account is Debit and utilities are CR in Chart of account, and if I pass an entry then and make utilities debit then in chart of accounts it must change from CR to DR in type column.
Also my accountant do not want to see (-) sign with negative he need type should change as per entries.
Let me explain more. Suppose I have 2 accounts (cash in hand) and (Utility Bills). The opening balance of both accounts in Chart of Accounts is:
Cash in Hand = 5000 DR
Utility Bills = 2000 CR
Now if I do an entry in cash payment so it will be
utility bills (DR) = 8000
cash in hand (CR) = 8000
Now after I do this entry the Chart of accounts must look like
Cash in hand = 3000 CR (because it is in negative due to I had only 5000) (now here the balance must show like -3000) but instead of (-) it showing 3000 and DR change to CR.
This is what I need to do:
Error after code
I guess you should keep the value as it is in database else you need to maintain another column to maintain account status anyway you have CR/DR and I am sure you kept it as boolean.
To convert value to absolute without any sign while displaying you can use below trick. To add CR/DR you have iterate through cells
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
If Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "YourAmountColumnName")) <0 Then
'Below line will remove (-) sign'
amt = amt * -1
e.Row.Cells(n).Text = "CR"
Else
e.Row.Cells(n).Text = "DR"
End If
End If
End Sub
It will return amount without any sign, If it is less than 0 obviously it is credit else it is debit.
In MSSQL you can use case for same, You have to check if amount is going negative
Type = CASE WHEN OpeningBalance <0 THEN Type="CR" ELSE Type="DR"
OpeningBalance = CASE WHEN OpeningBalance <0 THEN OpeningBalance= OpeningBalance*-1

VBA two dimensional arrays connecting to a database

I am working with vba in excel and a database in access. The access database is a table that contains 3 columns; OrderIDs which is a column of numbers saying what order the particular item was in, OrderDescription which is a column that contains the description of the item, and Item # which is a column that gives a number to each particular item (if the item is the same as another, they both are the same item).
I need to build a 2-dimensional array in excel using VBA holding which items were purchased in which orders. The rows will be the Order ID and the columns will be the Item ID. The elements of this array will contain an indicator (like True or a “1”) that indicates that this order contains certain items. For example, row 6 (representing order ID 6) will have “True” in columns 1, 5, and 26 if that order purchased item IDs 1, 5, and 26. All other columns for that order will be blank.
In order to do this, i think I will have to determine the max order number (39) and the max item number(33). This information is available in the database which I can connect to using a .connection and .recordset. Some order numbers and some item numbers may not appear.
Note also that this will likely be a sparse array (not many entries) as most orders contain only a few items. We do not care how many of an item a customer purchased, only that the item was purchased on this order.
MY QUESTION is how can I set up this array? I tried a loop that would assign the values of the order numbers to an array and the items numbers to an array and then dimensioning the array to those sizes, but it wont work.
is there a way to make an element of an array return a value of True if it exists?
Thanks for your help
It seems to me that the best bet may be a cross tab query run on an access connection. You can create your array with the ADO method GetRows : http://www.w3schools.com/ado/met_rs_getrows.asp.
TRANSFORM Nz([Item #],0)>0 AS Val
SELECT OrderNo
FROM Table
GROUP BY OrderNo
PIVOT [Item #]
With a Counter table containing integers from 1 to maximum number of items in a column (field) Num.
TRANSFORM First(q.Val) AS FirstOfVal
SELECT q.OrderNo
FROM (SELECT t.OrderNo, c.Num, Nz([Item #],0)>0 AS Val
FROM TableX t RIGHT JOIN [Counter] c ON t.[Item #] = c.Num
WHERE c.Num<12) q
GROUP BY q.OrderNo
PIVOT q.Num
Output:
OrderNo 1 2 3 4 5 6 7 8 9 10 11
0 0 0 0 0 0
1 -1 -1 -1 -1
2 -1 -1 -1 -1

Resources