I want to find specified text within a string in a given column, and count how many times that string is repeated throughout the entire column.
For example, Find "XX" within a string in a column and print to dialogue box the number of times that text was found.
Module m = current
Object o
string s
string x
int offset = null
int len = null
int c
for o in m do
{
string s = probeAttr_(o, "AttributeA")
x = o."Object Text" ""
if(findPlainText(s, "XX", offset, len, false)){
print "Success "
} else {
print "Failed to match"
}
}
I have tried to use command findPlainText but I am inadvertently passing every object as true.
As well I placed the output to print 'success' or 'Failed to match' so I can at least get a number count of what is being passed. Unfortunately it seems like everything is being passed!
My understanding is that 'probeAttr_(o, "AttributeA")' allows me to specify and enter what column to search. As well o."Object Text" "" now allows me to look within any object and search for any text contained. I also realize that variable x is not being used but assume it has some way of being used to solve this issue.
I only use DOORS at a surface level but having this ability will save other staff tons of time. I realize this may be accomplished using the DOORS advanced filtering capability but I'd be able to compound this code with other simple commands to save time.
Thank you in advance for your help!!
If you want to count every occurence of a specified string in a text in an attribute for all objects, I think Mike's proposal is the correct answer. If you are only interested, if the specified string occurs once in that object's attribute, I suggest using Regexp, as I find it very fast, quite powerful and nevertheless easy to use, e.g.:
Regexp reSearch = regexp2 "XX"
int iCounter = 0
string strOT = ""
for o in m do {
strOT = o."Object Text" ""
if (reSearch strOT) {
iCounter++
}
}
print "Counted: '" iCounter "'\n"
Most of this has been answered in (DXL/Doors) How to find and count a text in a string?
You can easily exchange the "print" with a counter.
Related
The full code itself is very convoluted, long, and novice-written; I'm trying to send x and z coordinates via rednet from a computer to a separate receiver turtle.
Receiver
rednet.broadcast("Awaiting Input!")
xAxis = rednet.receive() --Have tried tonumber(rednet.receive()) on both same result
zAxis = rednet.receive()
rednet.broadcast(xAxis) --Both values return 2 regardless of what I enter in the sender.
rednet.broadcast(zAxis)
sender
if(irrelevant == "genericstringhere") then
print(rednet.recieve()) --Awaiting Input!
io.write("X Axis: ") --Pizzaz
message = io.read() --Have tried using terms like X and xAxis.
rednet.broadcast(message) --Broadcast whatever tf I typed in.
sleep(0.3)
io.write("Z Axis: ") --More Pizzaz
message = io.read() --Have tried using terms like Z or zAxis
rednet.broadcast(message) --Broadcast whatever tf I typed in. again.
print(rednet.receive()) --Receive xAxis value from sender.
print(rednet.receive()) --Receive zAxis value from sender.
end
Both results at the end of execution return 2 instead of the value I input in io.read(). I have tried tonumber(), tostring(), and every combination of the two, and I can't seem to get it to work.
Per the documentation for rednet.receive:
Returns number senderID, any message, string protocol
The 2 you're seeing is the sender ID, not the message. Instead of xAxis = rednet.receive(), do senderId, xAxis = rednet.receive(), and similarly for everywhere else you assign its value. (If you were wondering why print showed you numbers before the messages, that's why.)
Basically, I have to go through all baselines of an object until I get the author who modified "_ReqStatus" attribute and copy that value in "_Ownr" attribute. Everything is working fine for the current baseline, but I cannot get through the older baselines of the module. I have to mention that I run the script for 2000 objects each one having at least 20 baselines.
My code looks like this:
//scriptul recunoaste obiectele cu "ReqStatus modifica"
pragma runLim, 0
Module m = current
History h
HistoryType ht
Object o
string attributName
string attributNameBaseline
string authorName
string newOwner
Baseline lBaseLine
noError()
for o in entire m do {
**for lBaseLine in module(o) do{ //These 2 code lines were my try to load all baselines
Module lBaseMod = load(module(o), false) //but with no results**
for h in o do
{
string owner = ""
attributName=""
attributName = h.attrName
authorName=""
owner = o."_Owner"
if isDeleted(o) then continue
if(attributName=="_ReqStatus")
{
authorName=h.author
//print authorName
//print "\n"
if(null owner)
{
print identifier(o)
print "\n"
newOwner = authorName
print newOwner"\n"
o."_Ownr" = newOwner
//print newOwner
break
}
}
}
}
}
ErrMess = lastError()
Thanks
Tony Goodman provides a script "Smart History Viewer" at http://www.smartdxl.com/content/?p=418, Michael Sutherland has one at https://www.ibm.com/mysupport/s/forumsquestion?id=0D50z00006HIGSUCA5, also, if you do a search on https://www.ibm.com/mysupport/s/forumshome for e.g. "dxl history" you might find some more code examples which should help you with this topic.
Your problem is the variable o. It is set only in the loop for o in entire m, it always refers to the o in the current version of m, never to the corresponding Object in a baseline. When you open the Module lBaseMod, o is not automatically reassigned.
So, use a new variable of type Object, set it to the Object in the baseline corresponding to o and browse through this new Object's history, see the linked scripts for reference.
Also, you should rework the flow of your script. With your approach, you open all the Baselines of m for each Object. In your case this means 2000 * 20 load and close. It will be much faster (though not necessarily less memory consuming) to open all the baselines of m in an outer loop, probably using a Skip list to collect the necessary information.
Also note that when you test your script, "print" becomes very slow after some time. It will be faster if you remember all the values that you want to print e.g. in a Buffer and print it at the end of your script, or write the output to a file.
I have created a DXL script that goes through every row of a couple modules. I am printing out certain rows and its information. I am doing this by having a for loop that goes through the rows and if it hits a row that I am interested in, I save the elements in the columns of this row to different string variables and print those string variables. The script does not take too long to run if the module does not have a lot of rows I am interested in but if I want to run multiple modules at the same time or if a module has a lot of rows I am interested in, the script can take hours. I can show the code that I have if this is not enough to come up with solutions. Any help would be appreciated!
I have tried using a skip list to store the print statements in that and then tried going through the skip list to print each value but that did not make the script run any faster.
string sep=","
for o in m do
{
string ver1= o."column1"
if (checkIf(o) && (!(isDeleted(o))))
{
string ver2= o."column2"
string onum=number(o)
""
string otext = o."Object Text"
print ver1 sep ver2 sep onum
}
}
Initial optimization:
for o in m do
{
if (checkIf(o) && (!(isDeleted(o)))) {
//This doesn't appear to be used?
//string otext = o."Object Text"
print o."column1" "," o."column2" "," number(o) "\n"
}
}
Reasoning: DOORS has a system in place called the string table that holds declared strings in memory- and doesn't necessarily do the best at clearing it out when appropriate. By constantly declaring strings in your loop, you might be bumping into the memory limits of that system.
Problem with this is that the results all end up in that 'DXL editor' little window, and then have to be copy and pasted somewhere else to actually use it.
Secondary optimization:
// Turn off runlimit for timing
pragma runLim , 0
// Set file location - CHANGE FOR YOUR COMPUTER
string csv_location = "C:/Users/Username/Desktop/Info_Collection.csv"
// Open stream
Stream out = append csv_location
// Set headers
out << "Module,Column 1,Column 2,Object Number" "\n"
// Define your loop constraints
Module m = current
Object o
// Run your loop
for o in m do
{
if (checkIf(o) && (!(isDeleted(o)))) {
//This doesn't appear to be used?
//string otext = o."Object Text"
out << fullName(m)","o."column1" "," o."column2" "," number(o) "\n"
}
}
close out
This will let you run the same script in different modules, all outputting to the same CSV file, which you can then load into Excel or your data manipulation engine of choice.
This keeps the data collection happening outside of DOORS, so if something goes awry, you can track down where it occurred.
My third optimization would be to use a list of modules in, say, excel as an input and do this analysis, but that might be going too far.
If this doesn't help, then we can start examining other issues.
Note- I still would like to know what 'checkIf' is/does.
If your objective is to speed up the execution of the script, since most of the objects are of no interest to you, the most effective way I know of is to filter out most of the objects that are not interesting, e.g., a filter which is obj."Object Text" != "" would filter out Headings, if you are just interested in requirements, obj."Object Text" contains "[Ss]hall" etc. Save as a view for later use.
for o in m do { respects the display set, so if you don't touch most of the objects it will speed it up a lot!
Hope this helps.
Don
I'm new to DXL and I want to extract the variables containing
_I_,_O_ and _IO_
from a module and export then to csv file. Please help me with this
EG:
ADCD_WE_I_DFGJDGFJ_12_QWE and CVFDFH_AWEQ_I_EHH[X] is set to some value
This question has two parts.
You want to find variables that contain those parts in their name
You want to export to a .csv file
Another person may be able to expand on a better way, but the only way coming to mind right now for 1. is this:
Loop over the attributes in the module (for ad in m do {}) and get the string of the attribute names.
I am assuming that your attributes are valued at _I_, _O_ or _OI_? Like alpha = "_I_"? Are these enumerate values?
If they are, then you only need to check the value of each object's attribute. If one of those are the attribute values, then add it to something like a skip list. Having a counter here would be useful, maybe one for each attribute, like countI, countO, countOI, you can then use the counters as keys for the put() function for the skip list.
Once you have found all the attributes then you can move on to writing to csv
Stream out = write("filepathname/filename.csv") // to declare the stream
out << "_I_, _O_, _OI_\n"
Then you could loop over your Skip lists at the same time
int ijk = 0; bool finito = false
while(!finito) do {
if(ijk<countI) {
at = get(skipListI, ijk)
out << at.name ","
}
else out << ","
if(ijk<countO) {
at = get(skipListO, ijk)
out << at.name ","
}
else out << ","
if(ijk<countOI) {
at = get(skipListOI, ijk)
out << at.name "\n"
}
else out << "\n"
ijk++
// check if the next iteration would be outside of bounds on all lists
if(ijk >= countI && ijk >= countO && ijk >= countIO) finito = true
}
Or instead of at.name, you could print out whatever part of the attribute you wanted. The name, the value, "name:value" or whatever.
I have not run this, so you will be left to do any troubleshooting.
--
I hope this idea gets you started, write out what you want on paper first and then follow that plan. The key things I have mentioned that would be useful here are Skip lists, and Stream write (or append, if you want to keep adding).
In the future, please consider making your question more clear. Are you looking for those search terms in the name of the attribute, or in the value of the attribute. Are you looking to print out the names or the values, or the what? What kind of format for the .csv are you going to have? Any information will help your question be answered.
I'm having some trouble with Lua. The thing is: there are some Lua codes I know what they do but I didn't understood them, so if the professors ask me to explain them, I wouldn't be able to do it.
Can you help me with this?
I know this code separates the integer part from the decimal part of a number, but I didn't understand the "(%d*)(%.?.*)$" part.
int, dec = string.match(tostring(value), "(%d*)(%.?.*)$")
This code insert on a table all the data from a text file, which is written following this model entry {name = "John", age = 20, sex = "Male"). What I didn't understand is how do I know what parameters the function load needs? And the last parameter entry = entry, I don't know if I got exactly its meaning: I think it gets the text_from_file as a piece of Lua code and everything that is after entry is sent to the function entry, which inserts it on a table, is it right?
function entry(entrydata)
table.insert(data, entrydata)
end
thunk = load(text_from_file, nil, nil, {entry = entry})
thunk()
That's it. Please, if it's possible, help me understand these 2 pieces of Lua code, I need to present the whole program working and if a professor ask me about the code, I want to be sure about everything.
For the first question, you need to learn a little about lua patterns and string.match.
The pattern (%d*)(%.?.*)$ is comprised of two smaller ones. %d* and %.?.*. The $ at the end merely indicates that the matching is to be done till the end of string tostring(value). The %d* will match 0 or more numerical values and store the result (if found, otherwise nil) t the variable int.
%.? matches a literal . character. The ? means that the . may or may not be present. The .* matches everything and stores them into dec variable.
Similarly, for the second code segment, please go through the load() reference. You have the following text in your file:
entry {name = "John", age = 20, sex = "Male")
It is equivalent to executing a function named entry with the parameter (notice that I used parameter and not parameters) a table, as follows:
entry( {name = "John", age = 20, sex = "Male") )
The last parameter to load defines the environment for the loaded string. By passing {entry = entry}, you're defining an environment in which you have a function named entry. To understand it better, look at the changes in the following segment:
function myOwnFunctionName(entrydata)
table.insert(data, entrydata)
end
thunk = load(text_from_file, nil, nil, {entry = myOwnFunctionName})
Now, the custom environment passed to load will have a variable named entry which is actually the function myOwnFunctionName.