How to add context references to a scenario programmatically - excel

I'm currently modifying the importer script Simple VBA Excel to EA importer v4 from bellekens.
I have succesfully imported a usecase containing scenarios and scenario steps. I'm looking for a way to add the context references programmatically.
I'm currently adding them manualy with the use case Properties > Rules > Scenarios > Context References.
Is there a way to add theses context references from the API?

I found the answer on http://sparxsystems.com/forums/smf/index.php?topic=4735.0
Basicly if you associate an actor with the use case it shows up in the context reference table.
to create the entry programmaticaly just add links between your Use case and actor programmatically.

I actually wrote a VBScript that does that. It looks into the logical class model and adds a context reference to it if that class name is used by the use case scenario step.
Here's that part that does the actual linking:
function linkDomainClassesWithUseCases(dictionary,regExp,usecases)
Session.Output usecases.Count & " use cases found"
dim usecase as EA.Element
'loop de use cases
for each usecase in usecases
Repository.WriteOutput "Link to Logical Data Model", "Processing use case: " & usecase.Name, 0
'first remove all automatic traces
removeAllAutomaticTraces usecase
'get all dependencies left
dim dependencies
set dependencies = getDependencies(usecase)
dim scenario as EA.Scenario
'loop scenarios
for each scenario in usecase.Scenarios
dim scenarioStep as EA.ScenarioStep
for each scenarioStep in scenario.Steps
'first remove any additional terms in the uses field
scenarioStep.Uses = removeAddionalUses(dependencies, scenarioStep.Uses)
dim matches
set matches = regExp.Execute(scenarioStep.Name)
dim classesToMatch
set classesToMatch = getClassesToMatchDictionary(matches, dictionary)
dim classToMatch as EA.Element
for each classToMatch in classesToMatch.Items
Session.Output "scenarioStep.Uses before " & scenarioStep.Uses
if not instr(scenarioStep.Uses,"LDM-" & classToMatch.Name) > 0 then
if len(scenarioStep.Uses) > 0 then
'add a space if needed
scenarioStep.Uses = scenarioStep.Uses & " "
end if
'add the name of the class
scenarioStep.Uses = scenarioStep.Uses & "LDM-" & classToMatch.Name
end if
'create the dependency between the use case and the Logical Data Model class
linkElementsWithAutomaticTrace usecase, classToMatch
Session.Output "adding link between " & usecase.Name & " and Logical Data Model class " & classToMatch.Name & " because of step " & scenario.Name & "." & scenarioStep.Name
next
'save scenario step
scenarioStep.Update
scenario.Update
next
next
next
end function
function linkElementsWithAutomaticTrace(sourceElement, TargetElement)
dim trace as EA.Connector
set trace = sourceElement.Connectors.AddNew("","trace")
trace.Alias = "automatic"
trace.SupplierID = TargetElement.ElementID
trace.Update
end function

Related

Validation of a dialog box for the update of fields "Mailmerge Fillin"

I'm looking for a way to validate those dialog boxes that pop up while updating a word document via excel vba.
The type of fields that I use is MailMerge Fields type "Fillin"
WordObj.ActiveDocument.MailMerge.Fields.AddFillIn
I'd like to write in them if possible too.
Update operation
Dialog box
It is by no means clear what you're trying to achieve. When you use:
ActiveDocument.MailMerge.Fields.AddFillIn
the resulting field doesn't show up in the document until something is done to cause it to update (e.g. performing the mailmerge). If you want the field to show up, use something like:
Dim wdFld As Object
With WordObj.ActiveDocument
Set wdFld = .Fields.Add(.Range.Characters.Last, -1, "QUOTE ""Default Text""", False)
wdFld.Code.Text = "FILLIN ""Some prompt"" \d ""Default Text"" \o"
End With
Other than that, you really do need to both explain how and why you're using a FILLIN field and post the code that updates it when the mailmerge is executed. After all, the use of a FILLIN field typically means the user is supposed to both make an input and press the OK/Cancel button.
To allow the specification of different ranges, prompts and defaults, you might use something like:
Sub FILLIN(StrBkMk As String, StrPrmpt As String, StrDflt As String)
Dim wdFld As Object
Dim quote As String
quote = char(34)
With WordObj.ActiveDocument
Set wdFld = .Fields.Add(.Bookmarks(StrBkMk).Range, -1, "QUOTE " & quote & StrDflt & quote, False)
wdFld.Code.Text = "FILLIN " & StrPrmpt & " \d " & StrDflt & " \o \* MERGEFORMAT "
End With
End Sub
where 'StrBkMk' is the name of a bookmark you want to position the field at. You'd then call the above code with something like:
Call FILLIN("FILLIN1", nom_signet, nouveau_texte_signet)
Or, if you're passing multi-word strings:
Call FILLIN("FILLIN1", "" & nom_signet & "", "" & nouveau_texte_signet & "")

Excel 2010 using Querytables and a few other things

I am handling a few Excel things professionally and are running into issues. I am forced to use web queries to pull an exportable Excel files with parameters defined in the excel document. For reasons we are not able to use power query and I have to drudge up my old programming knowledge and put something together. This is not anything critical, just improving our work environment.
I have nailed down most of the process but have to condense everything or else I will reach the maximum size limit very quickly running it sequentially.
The sections I am working with will be set in rows of 4 and as many columns as needed until there are no more. I am planning on basing the criteria in the code on the first cell of section 1 because there will be a value in this cell if there is more. The cells do need to be formatted as text due to the web connection URL but this has not caused any issues.
The code I have is more individual instruction for excel then any kind of VBA logic but it has worked for the bit I have tested. The issue I have is condensing it down to loop through the sections in the "Input" sheet. I apologize for any sloppy declarations or names as I am going to clean it up to add error messages and comments once I have something that is functional. (I have left out the url information since it is internal.)
Sub myworkbook()
Dim wsi As Worksheet
Dim sourl, sosd, sosd2, soed, soed2, sodm, soaf, soev, soexc, soflag, sobn As String
Dim sa, sb, sc, ea, eb, ec, dm, af, ev, exc, flag, bn As String
Set wsi = Sheets("Input")
sourl = "URL1"
sosd = "URL2"
sosd2 = "URL3"
soed = "URL4"
soed2 = "URL5"
sodm = "URL6"
soaf = "URL7"
soev = "URL8"
soexc = "URL9"
soflag = "URL10"
sobn = "URL11"
sa = wsi.Range("A2").Value
sb = wsi.Range("B2").Value
sc = wsi.Range("C2").Value
ea = wsi.Range("A4").Value
eb = wsi.Range("B4").Value
ec = wsi.Range("C4").Value
dm = wsi.Range("F2").Value
af = wsi.Range("I2").Value
ev = wsi.Range("L2").Value
Sheets("Sheet1").Activate
Cells.Select
Selection.Delete Shift:=xlUp
flag = wsi.Range("A11").Value
bn = wsi.Range("A14").Value
With ActiveSheet.QueryTables.add(Connection:="URL;" & _
sourl & sosd & sa & sosd2 & sb & sosd2 & sc & soed & _
ea & soed2 & eb & soed2 & ec & sodm & dm & soaf & af & _
soev & ev & soexc & exc & soflag & flag & sobn & bn, _
Destination:=Range("A1"))
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.AdjustColumnWidth = True
.Refresh BackgroundQuery:=False
End With
ActiveWorkbook.Connections("Connection").Delete
The issue I am having at the moment is I want to take 1 cell from section 1 and 1 cell from section 2, update the querytable and output the exported to a separate sheet then move on to the second cell in section 2 with the same cell in section 1. We do not have any issues with the formatting with the output as we use it to put together reports manually but it would help if I could use a variable for the destination in the query table to add a column but I have been unable to figure out how to use a range variable for the destination so far.
Using the example image the flow needs to be;
Start at A1
Use value of A1 and A7
Update querytable, output to another sheet
Use value of A1 and B7
Update querytable, output to same sheet with one column of space
etc...
Move to next section using values G1 and G7 when section 1 is done
Update querytable, output to separate sheet
etc..
I have been unable to figure out how to do this and do not have any code examples as nothing has been functional enough to use as a start. I have been playing around with using the name as a starting point and creating a new sheet based on the name to output the information to and having the macro delete all of the sheets before running a new set when the macro is executed. If this is something that can be done I would love to do this as it would make it more automated and need less input and just require the users to keep to the format in the document if new sections are added.
The main issues I have been having is the sparse amount of information on using query tables for web connections due to power query's implementation and my knowledge of Visual Basic has diminished to a point that I feel like a baby learning to walk.

Cycle and Edit Through XML Children Based On Values

I have an interface to cycle through XML child and edit them. Something like this:
The XML file looks as such:
<?xml version="1.0"?>
<catalog>
<query id="bk100">
<question>Do we have Docker security?</question>
<answer>Yes</answer>
<comment>None</comment>
<genre>Cloud</genre>
</query>
<query id="bk101">
<question>Do we have cloud security</question>
<answer>Yes</answer>
<comment>None</comment>
<genre>SCPC</genre>
</query>
<query id="bk100">
<question>Do we have Kubernetos security?</question>
<answer>Yes</answer>
<comment>None</comment>
<genre>Cloud</genre>
</query>
</catalog>
I am reading and storing the children as such in Global variabes:
xmlUrl = ThisWorkbook.Path & "\Blah.xml"
oXMLFile.Load (xmlUrl)
Set QuestionNodes = oXMLFile.SelectNodes("/catalog/query/question/text()")
Now once the user selects a Genre from the intrface (using a combobox or whatever), for example SCPC - I want the next and previous buttons to allow the to just loop through the questions and answers (and edit them) in the Genre SCPC
so for example, a Pseudo-implementation for the ``Next button` would look like:
'Next XML Node Iterartor
Private Sub btnNextEntry_Click()
Interate Where GenreNodes(i).NodeValue = "SCPC"
txtQuestion.Value = QuestionNodes(i).NodeValue
Pause 'When the user clicks Next again, the Next Node Data Is Showed
End Sub
and similarly something for the Previous button. Obviously I am out of logic here how to achieve this. As I also need to have editing and save functionality, I thought it was good idea to use index based iteration, but with the Genre based filtering, it doesn't make a lot of sense now and I am stuck.
Any tips ideas how I can handle this? Thanks.
Using Set QuestionNodes = oXMLFile.SelectNodes("/catalog/query/question/text()") for the question list makes it more difficult to filter than it needs to be. It's easier to use a list of the query nodes and then access the child nodes as required.
So, if you wanted to list all of the nodes then use:
Dim queryNodes As IXMLDOMNodeList
' ...
Set queryNodes = oXmlFile.SelectNodes("/catalog/query")
and you could then work with the values of the child nodes like this:
Dim node As IXMLDOMNode
For Each node In queryNodes
Debug.Print "Q: " & node.SelectSingleNode("question").Text & vbCrLf & _
"A: " & node.SelectSingleNode("answer").Text & vbCrLf & _
"C: " & node.SelectSingleNode("comment").Text & vbCrLf & _
"G: " & node.SelectSingleNode("genre").Text & vbCrLf & vbCrLf
Next node
If you then wanted to only work with nodes where the genre is "SCPC" then, it's just a case of changing the queryNodes list, like this:
Set queryNodes = oXmlFile.SelectNodes("/catalog/query[genre='SCPC']")
The code to access the child nodes doesn't change just because we have filtered the list differently. All of the changes are contained in how we create the queryNodes list. The code to update queryNodes could be called from the event handler for the combobox that allows the user to choose a genre.
We could adapt the code for printing all of the node values into a sub which prints the values of a specific node (as suggested by Tim Williams in the comments):
Sub printNode(node As IXMLDOMNode)
Debug.Print "Q: " & node.SelectSingleNode("question").Text & vbCrLf & _
"A: " & node.SelectSingleNode("answer").Text & vbCrLf & _
"C: " & node.SelectSingleNode("comment").Text & vbCrLf & _
"G: " & node.SelectSingleNode("genre").Text & vbCrLf & vbCrLf
End Sub
To control which node is displayed via your interface, use the Item property of the queryNodes list. The first node is queryNodes.Item(0), the next is queryNodes.Item(1) and so on.
If we use a variable called position to keep track of where we are in the list then the Previous button in your interface should make position = position - 1 and your Next button should make position = position + 1.
So, once the user presses Previous or Next, we would update position and then call printNode queryNodes.Item(position). There is always the chance that we have gone beyond either the start or the end of the list and this can be checked with If Not queryNodes.Item(position) Is Nothing before we try to call printNode.
For your specific case, you would need a sub to populate the fields in your interface. To do this, rename printNode to loadNode and, instead of printing to the Debug window, copy the relevant text from each child node into the corresponding field in your interface.
A saveNode function would just be the reverse of that - copy the value of each field in your interface into the text property of the relevant child node

Passing string result to query then export as csv

Good Afternoon,
I have an access query that contains a list of all my customers lets call that CUS
I have another query that has a list of ORDERS
I would like to write some VBS that cycles through the customer list and exports a csv file containing all orders that belong to that customer.
The vba would then move on to the next customer on the list and perform the same action.
Any help would be great.
Snippet of code below
almost there cant get the WHERE condition working it keeps displaying a popup for me to populate however the same string is feeding the msgbox fine here is a snippet below tht is within the loop
strcustcode = rs!OCUSTCODE
ordercount = rs!orders
TIMEFILE = Format$(Time, "HHMM")
MsgBox ([strcustcode] & " has " & [ordercount] & " orders")
StrSQL = "Select * From [24-ND_Cus] where [24-ND_Cus].[OCUSTCODE] = strcustcode "
Set qd = db.CreateQueryDef("tmpExport", StrSQL)
DoCmd.TransferText acExportDelim, , "tmpExport", "c:file.csv" db.QueryDefs.Delete "tmpExport" –
Don't use [ ] around VBA variables. Don't use parens for the MsgBox when you just want to give user a message. The parens make it a function that requires a response by user to set a variable.
MsgBox strcustcode & " has " & ordercount & " orders"
Concatenate the variable into the SQL statement. If OCUSTCODE is a text type field, use apostrophe delimiters for the parameter.
StrSQL = "Select * From [24-ND_Cus] Where [OCUSTCODE] = '" & strcustcode & "'"
I don't advise code that routinely modifies design and changing a query SQL statement is changing design. If the only change is filter criteria and a dynamic parameterized query won't work, I suggest a 'temp' table - table is permanent, data is temporary. Delete and write records to the table and export the table.

Remove Lotus Notes design element inheritance programmatically

As part of an effort to create a rudimentary revision control system, I would like to programmatically disable design element level inheritance on a Lotus Notes template. I have so far tried the following:
DXL export (ForceNoteFormat=true) + XSLT. This failed with a validation problem in the importer, on fields(!).
DXL export (ForceNoteFormat=false) + XSLT. Seems to work, but I'd rather not use a DXL solution for something this general.
An area I would like to explore:
Loop over all (design) Notes, remove the $Class item.
Does anybody have a suggestion on how to do this, or another approach that will remove inheritance?
The following sub seems to work, it removes the flag from any design element a 7.0.3 client can produce. I got the clues about NotesNoteCollection from Ian's blog entry on the same subject:
Private Sub clearDesignInheritance(db As notesdatabase)
On Error Goto errorthrower
Dim nc As NotesNoteCollection
Set nc = db.CreateNoteCollection(True) ' Select all note types...
nc.SelectDocuments=False ' ...except data documents.
Call nc.BuildCollection
Dim noteid As String
noteid = nc.GetFirstNoteId
Dim doc As notesdocument
Do Until noteid=""
Set doc = db.GetDocumentByID(noteid)
If doc.HasItem("$Class") Then
Call doc.RemoveItem("$Class")
Call doc.save(False,False,False)
End If
noteid = nc.GetNextNoteId(noteid)
Loop
Exit Sub
ErrorThrower:
Error Err, Error & Chr(13) + "Module: " & Cstr( Getthreadinfo(1) ) & ", Line: " & Cstr( Erl )
End Sub

Resources