After hours on hours of googling, I fail to find the solution to my problem.
Goal
Create a simple Excel application to post "return delivery" for multiple material documents in SAP.
My assumption is that I would need to utilize the BAPI "BAPI_GOODSMVT_CREATE".
Firstly I initiate the SAP Logon Prompt:
'------'
'Logon to SAP
'------'
Dim sapConn As Object ' Declare variant
Set sapConn = CreateObject("SAP.Functions") ' Create ActiveX object
With sapConn.Connection
.Destination = "somehost"
.ApplicationServer = "someserver.com"
.Client = "someclient"
.User = "someuser"
.Password = "somepassword"
.SystemNumber = "somesystem"
End With
If sapConn.Connection.Logon(1, False) <> True Then 'Try Logon
MsgBox "Cannot Log on to SAP"
End If
Then I define the function
'------'
'Define function
'------'
Dim objRfcFunc As Object
Set objRfcFunc = sapConn.Add("BAPI_GOODSMVT_CREATE")
Now, here is where it all stops. I've used this method to run other BAPI's by populating it through worksheet-iteration (looking at cell values).
Lastly (at the end of the function) I do the error handling:
If objRfcFunc.Call = False Then
MsgBox "Call failure" + objRfcFunc.Exception
End If
What I truly fail to understand, is which fields are the minimum required in order to execute the BAPI?
What BAPI field sto I need to populate?
If I do it manually in SAP through MIGO transaction, I require:
Material Document and Material Document Year.
Function I selected are "Return Delivery" -> "Material Document".
Obviously I lack some code to fill the data, but I simply do not know where to start out.
I've worked through this post, without any luck.
Any help or pointers to the right direction are greatly appreciated.
for a specific material document number (or multiple, if possible)
Not possible. BAPI_GOODSMVT_CREATE documentation denotes this in first lines that You can only create one material document each time you call up the method.
You should use GM_CODE 01 for goods movement 122 (return delivery), and the BAPI docu lists following mandatory fields for this GM_CODE:
Purchase order
Purchase order item
Movement type
Movement indicator
Quantity in unit of entry
ISO code unit of measurement for unit of entry or
quantity proposal
For known PO:
The following fields may have to be populated (this is not a complete list):
- Reason for movement (if set up in the system)
- Batch (if the material is handled in batches and no automatic batch assignment has been set up)
- Storage location (if no storage location us specified in the purchase order item)
The following fields can be populated (this is not a complete list):
- Item text
- Unloading point
- Delivery completed indicator
The following fields must not be populated (this is not a complete list):
- Reservation
- Receiving/issuing material
- Receiving/issuing plant
- Receiving/issuing storage location
It's all depends on the PO known/unknown and whether it should be created or not. Just RTFM.
The absolute minimum fields to be filled:
**Header**
DOC_DATE = 20050513 | Document date in document BLDAT
REF_DOC_NO = 345060A| Reference document number XBLNR
PR_UNAME = JOHNDOE | User name UNAME
GM_CODE = 01 | Assign code to transaction for BAPI goods movement
**Item**
MOVE_TYPE = 122 | Movement type (inventory management)
VENDOR = 1008056 | Vendor’s account number
ENTRY_QNT = 1.00 | Quantity in unit of entry
ENTRY_UOM = EA | Unit of entry
PO_NUMBER = ASA99834| Purchase order number
PO_ITEM = 00001 | Item Number of Purchasing Document
MVT_IND = B | Goods movement for purchase order Movement indicator
Related
I need some vba help at my Access project.
In our company we got different construction sites.
Each construction site have their own cost centre.
We have to make reports to each construction sites related to the cost centre.
These reports have their own continious number(related to the cost centres)
I got a formular, where I can choose the cost centre and want to be shown the latest report number +1, when making a new input, so no mistakes can happen for users.
Formular looks like this
Nr. is related to the textfield Nummer with the content raumBTBNR for the increasing Report numbers. Kostenstelle got the combo box called KostenstelleAuswahl with the content raeumKostenstelleIDRef for the cost centres.
Code so far: (credits by Gustav)
Private Sub Nummer_GotFocus()
Dim NextNumber As Long
highest Rep.Nr. related table Content of KostenstelleAuswahl
NextNumber = DMax("[raumBTBNR]", "[tbl_Raeumstellen]", "[KostenstellenIDRef] = " & Me!KostenstelleAuswahl.Value & "") + 1
Me!Nummer = NextNumber
End Sub
My solution right now is a query, where i count the number of the reports, related to the cost centres. But it does not fill automatically and is more worse than nice. Which is saved at MaxNr
Example in my form
I would appreciate some help!:)
OK, then this should work - when selecting Kostenstelle:
Private Sub KostenstelleAuswahl_AfterUpdate()
Dim NextNumber As Long
NextNumber = DMax("[raumBTBNR]", "[tbl_Raeumstellen]", "[raeumKostenstelleIDRef] = " & Me!KostenstelleAuswahl.Value & "") + 1
Me!Nr.Value = NextNumber
End Sub
I have created a program that tracks our families spending. It essentially one big sum if calculation. Every month I download our credit card and debit card charges from our bank and have my macros sort and then categorize each charge.
I am trying to make the process easier so my wife and in laws can use the program as well.
I am trying to insert a code that will take a variable that is inputted into a input box and put the said variable in to the sum if equation. The variable will be the name of the charge. I would like for my wife to be able to input the tag for charge into the input box (the string that triggers the sum if) and then have excel automatically add it to the database of charges I use. This needs a wild card attached to it because some of our monthly charges have really weird computer generated names associated with them.
I have come up with a code so far and by my research it should work....but it doesnt. What am I doing wrong here?
Sub ab_formula()
'
'ab_formula Macro
'
Dim NameExpense As String
Dim TagForExpense As String
NameExpense = InputBox("Enter the name of the new expense", "New Expense", "Type Here", 0, 0)
TagForExpense = InputBox("Enter the name of the new expense", "TagForExpense", "Type Here", 0, 0)
Range("J23:J2000").Select
ActivateCell.FormulaR1C1 = "SUMIF(C[-8]," * "&TagForExpense&" * ",C[-7])"
Range("I23").Select
ActiveCell.FormulaR1C1 = NameExpense
End Sub
Please let me know if I can clarify anything.
I'm trying to optimize a small patch of code that's connecting to our servers over and over again. To start off, here's the patch of code
Dim sale as Sale()
With sale
If .CustomerID > 0 Then
.CustomerName = CCCustomer.SelectByID(.CustomerID).FirstNameLastName
Else
.CustomerName = "Cash Sale"
End If
End With
So the issue is that if you have, say 50 customers that this is iterating through, it takes a long long time to get through the data, as for each customerID all you have to access the CCCustomer object, connect to the database, find the customer by ID, and then select the FirstNameLastName from the object.
My first thought was to just pull a list or array of ALL the customers right off the bat, and then match them by ID, but this seems to take even LONGER
Dim sale as Sale()
With sale
Dim allCustomers() = CCCustomer.SelectAll
If .CustomerID > 0 Then
.CustomerName = Array.FindIndex(allCustomers, Function(c) c.CustomerID = .CustomerID)
Else
.CustomerName = "Cash Sale"
End If
End With
(This code returns the customerId, not the names, but it still takes forever either way)
The only other option I can think of would be a complete rewrite of multiple stored procedures and updating the object to just natively hold the customers name as well as the customerID, but figured I'd check in before I go about completely ripping apart the rest of the program.
So does anyone know a good way to get a decent load time for something like this when you're pulling from a database?
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
I'm aware this question has been asked a few times on here already, and the common answer seems to be that this error arises when old child objects aren't deleted correctly when being modified or removed from their parent. However, I'm attempting to do neither of these things, and I'm still getting the error.
My system works roughly like this:
I have a pencil factory which makes pencils of many different varieties, and these are sold in sets. The pencil cases which these sets come in are also manufactured by me. Each individual pencil can be uniquely identified, as can the cases. Pencils cannot be sold or owned independently from their case, however if a new pencil is designed and added to an existing case, we send one of these pencils out to each customer who has already purchased that particular case.
So we have five tables here:
PencilCase
id
style
Pencil
id
colour
pencilCase
CustomerPencilCase
serialNumber
pencilCase
customer
CustomerPencil
serialNumber
pencil
customerPencilCase
Customer
id
name
The following is a function used to create a new CustomerPencil, generate a unique serial number for it, and add it to the database. 'db.SaveChanges()' is called here in order to reduce the risk of collisions.
Private Function CreateNewCustomerPencil(pencil As Pencil, customerPencilCase As CustomerPencilCase) As CustomerPencil
Dim customerPencil As New CustomerPencil
Dim serialNumber As String
Dim isUnique As Boolean = False
While isUnique = False
serialNumber = GenerateSerialNumber()
If (From cp In db.CustomerPencils Where cp.serialNumber = serialNumber).Count < 1 Then
isUnique = True
customerPencil.serialNumber = serialNumber
customerPencil.pencil = pencil
customerPencilCase.customerPencils.Add(customerPencil)
db.SaveChanges()
End If
End While
Return customerPencil
End Function
So, as explained above, there are two cases where this function is called. The first is when a new Pencil is added to a PencilCase. In this instance, a CustomerPencil associated with the new Pencil is added to each CustomerPencilCase that corresponds to the PencilCase. This subroutine works perfectly in conjunction with the above function.
Private Sub AssignPencilToPencilCase(pencil As Pencil, pencilCase As PencilCase)
Dim customerPencilCaseQuery = From cpc In db.CustomerPencilCases Where cpc.pencilCase.id = pencilCase.id Select cpc
Dim customerPencilCases As List(Of CustomerPencilCase) = customerPencilCaseQuery.ToList
For Each customerPencilCase As CustomerPencilCase In customerPencilCases
Dim customerPencil = CreateNewCustomerPencil(pencil, customerPencilCase)
Next
End Sub
The other case is when a Customer purchases a new CustomerPencilCase. In this instance, for each Pencil that exists in the corresponding PencilCase, a new CustomerPencil must be created. This is the problematic subroutine, which fails when db.SaveChanges() is called in the above function.
Private Sub AssignPencilCaseToCustomer(pencilCase As PencilCase, customerPencilCase As CustomerPencilCase)
Dim pencils = GetPencils(pencilCase.id)
For Each pencil As Pencil In pencils
Dim customerPencil = CreateNewCustomerPencil(pencilCase, customerPencilCase)
Next
End Sub
I've been stuck on this problem for a number of days now, and would be ever so grateful if anyone can suggest what I may be doing wrong.
Phew, managed to fix it. Thank you very much, Justin, for your comment which nudged me in the right direction.
In this instance the problem lay in the Pencil object I was sending to the CreateNewCustomerPencil function. The one passed initially to AssignPencilToPencilCase was retrieved directly from the database earlier on and thus worked fine. However, the ones retrieved by GetPencils in the broken subroutine were actually altered slightly after retrieval. This caused EF to think that I'd modified those Pencils, meaning the existing Pencils in the database became orphaned, resulting in the non-nullable foreign key error.
For the life of me, I just cannot seem to get this to work. Here is the situation: I am trying to add the already existing customer custom field (already had a definition, but no value) to an estimate that I am currently creating via QBSDK 12. So far, I can add the estimate, the custom fields to the line items, but not the custom fields belonging to the customer in the estimate header area (reserved for customer information).
Here is my attempted code for the header (doesn't work):
If Not (DE.sconProof(x) Is Nothing) Or Not (DE.sconProof(x) = "") Then
Dim DataExtModRq As IDataExtMod
DataExtModRq = requestMsgSet.AppendDataExtModRq
' DataExtModRq.ORListTxn.TxnDataExt.TxnID.SetValue(sEstID)
DataExtModRq.OwnerID.SetValue("0")
DataExtModRq.DataExtName.SetValue("Proof Required")
DataExtModRq.ORListTxn.TxnDataExt.TxnDataExtType.SetValue(ENTxnDataExtType.tdetEstimate)
DataExtModRq.ORListTxn.ListDataExt.ListObjRef.FullName.SetValue(DE.sconCompany(x))
DataExtModRq.DataExtValue.SetValue(DE.sconProof(x))
End If
Here is my working code for line items within the estimate (Does work):
If Not DE.sitemDateNeeded(i) = "" Then
Dim DataExt53 As IDataExt
DataExt53 = EstimateLineAdder.EstimateLineAdd.DataExtList.Append()
'Set field value for OwnerID
DataExt53.OwnerID.SetValue("0")
DataExt53.DataExtName.SetValue("In Hands By")
'Set field value for DataExtValue
DataExt53.DataExtValue.SetValue(DE.sitemDateNeeded(i))
End If
If Not DE.sitemSPC(i) = "" Then
Dim DataExt54 As IDataExt
DataExt54 = EstimateLineAdder.EstimateLineAdd.DataExtList.Append
DataExt54.DataExtName.SetValue("SPC")
DataExt54.DataExtValue.SetValue(DE.sitemSPC(i))
End If
The error message say's I am missing the TxnID but I am not modifying the estimate, I am creating a new one. I have tried the "IDataExt" as well but that doesn't work any better. If I need to save the newly created estimate, and then go back and add the TxnID, that would be really weird, and I'm not sure of a simple way to do that. I should be able to add data to the custom field in the header portion of the estimate without going through so much "hoopla". Please help me if you know the answer.
I figured it out...
If Not (DE.sconProof(x) Is Nothing) Or Not (DE.sconProof(x) = "") Then
Dim DataExtModRq As IDataExtMod
DataExtModRq = requestMsgSet.AppendDataExtModRq
DataExtModRq.DataExtName.SetValue("Proof Required")
DataExtModRq.DataExtValue.SetValue(DE.sconProof(x))
DataExtModRq.OwnerID.SetValue("0")
'DataExtModRq.ORListTxn.TxnDataExt.TxnDataExtType.SetValue(ENTxnDataExtType.tdetEstimate)
DataExtModRq.ORListTxn.ListDataExt.ListDataExtType.SetValue(ENListDataExtType.ldetCustomer)
DataExtModRq.ORListTxn.ListDataExt.ListObjRef.FullName.SetValue(DE.sconCompany(x))
'DataExtModRq.ORListTxn.TxnDataExt.TxnID.SetValue(sTxnID)
End If