How can i add this other condition to this code? - basic

i have this subroutine that i use to make labels. for some reason i cant just make another subroutine where instead of "CGI_SAMPLE_LABEL" it uses "YCI_SAMPLE_LABEL" because of other subroutines. any suggestions on how i can add this so that it chooses either one or the other. if tried using WHERE OR but that didn't work. i edited some of the tags because LIMS basic language is also like smalltalk.
LabelType = "CGI_SAMPLE_LABEL"
pTableNameStr = "SAMPLE"
pLabelNameStr = "CGI_SAMPLE_LABEL"
'Breakpoint(aReason)
NumSamples = Ubound(selectedObjects, 1)
FOR X = 1 TO NumSamples
SampleNumber = selectedObjects[x]
pKeyNameArr[1] = SampleNumber
pNumLabelsInt = 1
pLabelNameStr = "CGI_SAMPLE_LABEL"
pReasonStr = "Auto Label Generation"
pActivityStr = "Label printed for sample logged event"
GOSUB FN_LABEL_PRINT_ALL
NEXT 'Sample
RETURN

Related

Wildcards/patterns with .Tables("PARA") when executing RFC INST_EXECUTE_REPORT

I'm using Excel and VBA to get SAP to download data from SAP through RFC using INST_EXECUTE_REPORT.
It works like a charm when I have specific input parameters. I just build up .Tables("PARA") with the screen name of the parameter and the desired value. I can even use this method for date ranges.
The challenge is when I don't know exactly the input parameters. For example, I wanted to identify all internal orders with a specific text in the description, e.g. CODE40.
Is there any way to use wildcards with INST_EXECUTE_REPORT? When the program passed into INST_EXECUTE_REPORT is executed normally as a transaction on screen, I can set the parameter to *CODE40* and SAP automatically applies a wildcard search. But I can't get that to work with VBA.
I can simulate using wildcards when accessing individual tables with BBP_RFC_READ_TABLE by using LIKE statements in the selection option, but I need a similar functionality for whole reports, not individual tables.
Can anyone help?
Best regards,
The code I'm using is as follows:
Set ObjR3_EXECUTE_REPORT = ObjR3.Add("INST_EXECUTE_REPORT")
With ObjR3_EXECUTE_REPORT
Set ObjR3_EXECUTE_REPORT_Name = .Exports("PROGRAM")
Set ObjR3_EXECUTE_REPORT_Para = .Tables("PARA")
Set ObjR3_EXECUTE_REPORT_Result = .Tables("RESULT_TAB")
Set ObjR3_EXECUTE_REPORT_Output = .Tables("OUTPUT_TAB")
End With
ObjR3_EXECUTE_REPORT_Name.Value = ReportName
'Build up the table with the fields to be selected
f = 1
For a = LBound(aParameters) To UBound(aParameters)
aParameterPair = aParameters(a)
aParameterInput = aParameterPair(UBound(aParameterPair))
sParameterName = aParameterPair(LBound(aParameterPair))
For c = LBound(aParameterInput) To UBound(aParameterInput)
sParameterInput = aParameterInput(c)
ObjR3_EXECUTE_REPORT_Para.AppendRow
ObjR3_EXECUTE_REPORT_Para(f, "PARA_NAME") = sParameterName
ObjR3_EXECUTE_REPORT_Para(f, "PARA_VALUE") = sParameterInput
Debug.Print sParameterName & " " & sParameterInput
f = f + 1
Next c
Next a

How to use Autofill/Filldown with a range of values

I have been trying to get Excel to apply a formula over a set of columns and then extend the pattern across the entire set of rows.
This has led to the following code:
For i = 0 To avgsheetNames.Count - 1
If Contains(CStr(avgsheetNames(i)), "Scores") = True Then
With mainWorkBook.Worksheets(avgsheetNames(i))
strFormulas(1) = "=SUM(Aggregated_Internal_Scores!I2:I7)/6"
strFormulas(2) = "=SUM(Aggregated_Internal_Scores!J2:J7)/6"
strFormulas(3) = "=SUM(Aggregated_Internal_Scores!K2:K7)/6"
strFormulas(4) = "=SUM(Aggregated_Internal_Scores!L2:L7)/6"
strFormulas(5) = "=SUM(Aggregated_Internal_Scores!M2:M7)/6"
strFormulas(6) = "=SUM(Aggregated_Internal_Scores!N2:N7)/6"
strFormulas2(1) = "=SUM(Aggregated_Internal_Scores!I8:I13)/6"
strFormulas2(2) = "=SUM(Aggregated_Internal_Scores!J8:J13)/6"
strFormulas2(3) = "=SUM(Aggregated_Internal_Scores!K8:K13)/6"
strFormulas2(4) = "=SUM(Aggregated_Internal_Scores!L8:L13)/6"
strFormulas2(5) = "=SUM(Aggregated_Internal_Scores!M8:M13)/6"
strFormulas2(6) = "=SUM(Aggregated_Internal_Scores!N8:N13)/6"
mainWorkBook.Worksheets(avgsheetNames(i)).Range("C2:H2").Formula = strFormulas
mainWorkBook.Worksheets(avgsheetNames(i)).Range("C3:H3").Formula = strFormulas2
mainWorkBook.Worksheets(avgsheetNames(i)).Range("C2:H3").AutoFill Destination:=mainWorkBook.Worksheets(avgsheetNames(i)).Range("C2:H32")
End With
End If
As you can see I have tried to provide the pattern I am going for where the values extracted from the "Aggregated_Internal_Scores" sheet should follow the pattern I2:I7 > I8:I13 > I14:I19 and so on.
However, when the macro has been executed what I get is I2:I7 > I8:I13 > I4:I9 > I10:I15?
It seems Excel is taking the block C2:H3 as the pattern and just incrementing by 2 at the start of every block.
Can you anyone explain where I have gone wrong and how I can specify that I want the extraction of sheet values to follow a certain pattern?
Thank you in advance!
Use:
mainWorkBook.Worksheets(avgsheetNames(i)).Range("C2:H32").Formula = "=SUM(INDEX(Aggregated_Internal_Scores!I:I,(ROW($ZZ1)-1)*6+2):INDEX(Aggregated_Internal_Scores!I:I,(ROW($ZZ1)-1)*6+7))/6"
Replace everything inside the If with that.
If one has Office 365 with dynamic array formula then use:
mainWorkBook.Worksheets(avgsheetNames(i)).Range("C2:H32").Formula2 = "=SUM(INDEX(Aggregated_Internal_Scores!I:I,SEQUENCE(6,,(ROW($ZZ1)-1)*6+2))/6"

How to loop through XML-nodes and validate if values exists?

I have through an API fetched my data as an XML, and I wish to cycle through nodes (there are several of the same type) and add them to certain fields/a table.
Example from the XML-file:
<HistRating
xmlns="">
<EndrAr>2020</EndrAr>
<EndrMnd>7</EndrMnd>
<Rating>A</Rating>
</HistRating>
<HistRating
xmlns="">
<EndrAr>2019</EndrAr>
<EndrMnd>6</EndrMnd>
<Rating>A</Rating>
</HistRating>
I have tried the following format (at this point the XML I need is in a string in xmlDoc xmlDoc = CreateObject("MSXML2.DOMDocument.6.0"). Fully aware that this is not a really "sexy" way to write it, but I'm new at this game:
Set nodeXML = xmlDoc.getElementsByTagName("EndrAr")
Range("G1").Value = nodeXML(1).Text
Range("H1").Value = nodeXML(2).Text
Range("I1").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("EndrMnd")
Range("G2").Value = nodeXML(1).Text
Range("H2").Value = nodeXML(2).Text
Range("I2").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("Rating")
Range("G3").Value = nodeXML(1).Text
Range("H3").Value = nodeXML(2).Text
Range("I3").Value = nodeXML(3).Text
This works great as long as all three items are there. Unfortunately that is not given. If it is a new company i.e. (3) wont exist (there is one line per year above), and I would like to either set the cell to Blank or No value or something.
The result from when I run the above code:
But if I try to add a line 4 to test what happens if value does not exists I get the following (for obvious reasons)
What I would love some help with is:
Can I by some "magic" add a ifmissing (tried it, but could not get it to work)?
Other ways to add a if variable is not found, input following into cell
Or are there a complete different way I should have solved this?
This is to add accounting data from last X available years (where X is ie 4, or less if not 4 is available) from 30 nodes.
You could use an Error trapping Function. Note in the code below we choose not to use the returned boolean.
Dim myTest as String
.
.
TryReadingXmlNode nodeXML,1, myText
Range("G1").Value = myText
.
.
Public Function TryReadingXmlNode(ByVal ipNode as object, ByVal ipIndex as Long, ByRef opText as string) as boolean
On Error Resume Next
opText=ipNode.Item(ipIndex).Text
TryReadingXmlNode=Len(opText)>0
If err.number>0 then opText="NoValue"
on Error Goto 0
End Function
Start by querying all of the HistRating elements, then loop over that collection:
Const MAX_YEARS As Long = 4
Dim ratings, rating, c As Range, i as Long
Set c= Range("A1")
Set ratings = xmlDoc.getElementsByTagName("HistRating")
For Each rating in ratings
c.offset(0, i) = rating.getElementsByTagName("EndrAr")(0).Text
c.offset(1, i) = rating.getElementsByTagName("EndrMnd")(0).Text
c.offset(2, i) = rating.getElementsByTagName("Rating")(0).Text
i = i + 1
If i >= MAX_YEARS Then Exit For 'exit if processed enough nodes
Next rating

How to export text from annotation fields in Nuance Power PDF to Excel using VBA?

I am trying to export some text from annotation fields in Nuance Power PDF to Excel using VBA. I added the Nuance Power PDF reference to Excel VBA (PDF Plus).
I used it and it works well but the text returned from fields is empty.
Set PDFApp = CreateObject("NuancePDF.App")
Set dvDoc = CreateObject("NuancePDF.DVDoc")
dvDoc.Open("\\adpdc-2\Users$\a.goudinoux\Documents\Macro Formulaire\fiche.pdf")
Set ddDoc = dvDoc.GetDDDoc()
Set ddPage = ddDoc.AcquirePage(0)
nbannots = ddPage.GetNumAnnots() - 1
For i = 0 To nbannots
Texte = ""
Set ddAnnot = ddPage.GetAnnot(i)
Set ddText = ddDoc.CreateTextSelect(0, ddAnnot.GetRect())
ThisWorkbook.Sheets(1).Cells(1, i) = ddAnnot.GetTitle()
For k = 0 To ddText.GetNumText()
Texte = Texte & ddText.GetText(k)
Next
ThisWorkbook.Sheets(1).Cells(2, i) = Texte
Next
Part of the PDF document :
Results :
As you can see the first line is working but not the second one.
I thought the problem was with ddText but ddText.GetNumText() gives the right number of text elements in the text selection (ex : 2, 5, 4, etc...) when I run my program in Debug Mode.
I think the problem is from the function GetText(k).
I made it work once but I can't find my code back..
Do you see any mistake ?
Either your annotations are more complex than indicated or you're overthinking it.
Just read the annotation with GetContents and call it a day.
Set PDFApp = CreateObject("NuancePDF.App")
Set dvDoc = CreateObject("NuancePDF.DVDoc")
dvDoc.Open("\\adpdc-2\Users$\a.goudinoux\Documents\Macro Formulaire\fiche.pdf")
Set ddDoc = dvDoc.GetDDDoc()
Set ddPage = ddDoc.AcquirePage(0)
nbannots = ddPage.GetNumAnnots() - 1
For i = 0 To nbannots
Set ddAnnot = ddPage.GetAnnot(i)
ThisWorkbook.Sheets(1).Cells(1, i) = ddAnnot.GetTitle
ThisWorkbook.Sheets(1).Cells(2, i) = ddAnnot.GetContents
Next i

Searching for a defined set of values in a string

I'm trying to search a string for a set of values and return the value ONLY if the string matches exactly with one of the set.
My original expression was as so:
title = "MrS"
setTitles = {"Miss", "Mr", "Mrs", "Dr", "Ms"}
title = (title:gsub("%w",string.lower)):gsub("^l", string.upper)
if string.match(title, setTitles) ~= nil then title = title else title = "XX" end
I then realised I needed some way of cycling through the values so got to here:
title = "MrS"
setTitles = {"Miss", "Mr", "Mrs", "Dr", "Ms"}
title = (title:gsub("%w",string.lower)):gsub("^%l", string.upper)
for i = 1, 5 do
if string.match(title, setTitles[i]) ~= nil
then title = title
else title = "XX"
end
end
Except that just returns "XX" every time.
I know it's probably quite simple and obvious, but I can't seem to find a solution and would really appreciate a hand!
Here is why your code is not working. Your first iteration of the loop uses Mrs and checks if it matches Miss, and it does not so it changes title to XX and thus no following checks can ever match.
You cant change title until you have checked all your possible values first.
By adjusting your code to use a matchFound variable to determine if the change is needed you can fix this problem:
local matchFound = false
for i = 1, 5 do
if string.match(title, setTitles[i]) ~= nil then
matchFound = true
break
end
end
if matchFound == false then
title = "XX"
end
print(title)
Additionally your code can give false matches for Mr rather then Mrs this is because Mr will match inside Mrs or any string that starts with Mr. To change this you can adjust your call of string.match to:
string.match(title, "^".. setTitles[i] .. "$")
This forces string.match to insure that the first and last chars of the pattern are also the first and last chars of the string passed to it.
As a suggestion, Rather then using string.match, make your setTitles a proper set like:
local setTitles = {["Miss"] = true, ["Mr"] = true, ["Mrs"] = true, ["Dr"] = true, ["Ms"] = true}
Then your check becomes:
title = setTitles[title] and title or "XX"
Lua resource on Sets:
https://www.lua.org/pil/11.5.html
http://lua-users.org/wiki/SetOperations
You shouldn't change the title variable in the for loop.
You can try this code:
--title = "MrS"
title = "MrX"
setTitles = {"Miss", "Mr", "Mrs", "Dr", "Ms"}
title = title:gsub("%w", string.lower) -- mrs
title = title:gsub("^%l", string.upper) -- Mrs
ismatch = false
for i = 1, 5 do
print(title, setTitles[i])
if tostring(title) == tostring(setTitles[i]) then
ismatch = true
print("matched")
return
end
end
if ismatch then title = title else title = "XX" end
print(title)
Hope this helps.

Resources