uipath "for each" being time-consuming - excel

i implemented a normal 'for each'-Loop (not the excel specific for each row) in my UIPath Project.
The for-each Loop looks through a datatable with previously retrieved data from an excel file.
The for-each-loop then itererates through the Data with an if-else behind it.
Lets say it is as follows:
for each item in dataTable:
if (content of item == "10")
{
write cell: "Test" into A + index.ToString()
// leads for instance to writing into excel column 'A1'
}
else
{ write cell: "ElseTest" into for C + index.ToString() }
-- I used the syntax just for presentation-purposes.. :D
-> So the problem is:
writing into the cells takes so much time, where else putting out a MessageBox with random text inside the if and elses is done in milli-seconds, so the for-each-loop can't be the problem...
I ran that process with task manager opened and found out that Excel starts up, CPU percantage increases heavily, immidiately jumps to 0%... same happens again, for each iteration through the loop.
Why is that?
Is there a more optimised way to do that?
I need the for-each structure, because I need to check if it's either value 1 or value 2 inside the cell...

One possible option is to use the Read Range activity, manipulate the DataTable object itself, and then at the end write said object back to the same range using the Write Range activity.
Here's an example. My sheet contains 100 rows with all numbers from 1 to 100 in column A. Whenever there's a "1" in the cell, the data will be overwritten (in the DataTable object).

I think opening excel on each iteration is the time consuming part so I suggest
open excel before your for each
use attach window activity (https://activities.uipath.com/docs/window-scope) inside your foreach to set focus on excel file
close excel after your foreach or when you are done with the excel file
I would strongly recommend reframework (https://github.com/UiPath/ReFrameWork/tree/master/Framework) if you are not using it. It is an excellent starting point for RPA projects.
If you are using reframework you can open your excel file in InitAllApplications.xaml do your operations in Process.xaml and close your excel inside CloseAllApplications.xaml.

Related

How can I stop REF errors?

=IFERROR(VLOOKUP("Processed Units Forecast",'IB ALPS'!$A$59:$K$1000,MATCH(Date1,INDEX('IB ALPS'!$1:$1048576,3,1):INDEX('IB ALPS'!$1:$1048576,3,11),0),FALSE),"N/A")
Hello, so I'm having an issue with this formula. I have a macro that deletes some of the DATA on the IB ALPS sheet. By the time the macro is finished, all of the referenced cells/ranges are fixed, but somewhere in the middle it creates a REF error # $A$59:$K$1000(because of that split second where the cells are deleted). How can I stop excel from editing the function in that 1 second down time that the macro has, or how can I edit the function to keep referring to that range without immediately adding a REF.
If you have the ability to edit the macro, you can temporarily disable calculation for your sheet while deleting the cells:
ActiveWorkbook.Sheets("IB ALPS").EnableCalculation = False
' Some code that deletes rows goes here
ActiveWorkbook.Sheets("IB ALPS").EnableCalculation = True
This should prevent the functions on that sheet from thinking that anything has gone wrong. See the Microsoft documentation on this property for more information.

Want to read only active cell values from excel in blueprism

How do I extract only the available active cell values into a collection? I've got an excel file that has 10 cell values but the blue prism process is reading is entire rows from the excel. Thanks in advance.
Well, to do that you'll need two actions:
1) The action that will return the active range
2) Action: "Get Worksheet Range as Collection"
The first action is not supplied out of the box, in standard "MS Excel VBO", but the code is really simple to write. It's should be just a code stage with one line of code
input: handle as number, Workbook_Name as string
output: range as string
x = GetWorkbook(handle, Workbook_Name).ActiveSheet.Selection.Address
(Disclaimer: I haven't tested that code)
The second one action is I think standard one, so you should be able to find it in your object.

Copying MSProject information to Excel

I have a macro-enabled Excel workbook that opens a series of MSProject files, applies filters to a specific column, and copies portions of the visible range to Excel. The code for the copy action looks like this:
For Each Task In ActiveSelection.Tasks
If Not Task Is Nothing Then
TargetWS.Cells(Row, 3) = Task.PercentComplete / 100
TargetWS.Cells(Row, 4) = Task.Name
TargetWS.Cells(Row, 5) = Task.Start
TargetWS.Cells(Row, 6) = Task.Finish
TargetWS.Cells(Row, 7) = Task.BaselineFinish
Row = Row + 1
End If
Next Task
Essentially, I am looping through every row in the filtered range and copying each column one at a time. As you can imagine, this takes a long time.
My hope is to replace this iterative method with the standard set of actions I would use in Excel VBA: define first & last rows, then use one copy action for each column I want. This would greatly reduce the number of copy actions required to complete the task, which should provide a speed increase.
In Excel VBA, the code I want would look something like this, having defined the last row:
TargetWS.Range("A2:" & LastRow).Copy Destination:= (destination cells)
I know how to find the last visible task in Project, but am unfamiliar with range selection. Could someone fill in the gaps?
Thanks!
Your current method takes a sound approach, so instead of changing the method, try improving the performance.
The slowest part of your code right now isn't that you are looping through the tasks one-by-one, it's that you are writing to Excel cell-by-cell. The first step you can take is to write all data for a single task at one:
TargetWS.Range("C" & Row & ":G" & Row) = Array(Task.PercentComplete / 100, _
Task.Name, Task.Start, Task.Finish, _
Task.BaselineFinish)
Once you are comfortable with that, then you can move on to writing blocks of data at a time. To do this, store the data in a 2-dimensional array and only write it to Excel when you are done looping through the tasks. (Note, if you have many thousands of tasks, you may need to write the data in smaller chunks.)
Also, make sure you have turned calculation off in Excel. This will improve performance as can turning off screen updates. Just make sure you reset both application settings when your code is completed (even it if finishes with an error).
One last tip, avoid naming variables the same as objects (e.g a Task object named Task).

LUA: How can extract specific values from a xls or csv file and save them as variables?

I'm a beginner in lua (at best).
I have a *.lua script that at some point has a function that when called sets a set of variables. (or updates them)
These specific variables should be extracted from a xls or csv file - something that can be managed by excel.
So in excel I have rows and columns like this:
valuefield_1 100 20 30
valuefield_2 60 150 40
valuefield_3 80 90 170
etc.
I want to be able to search for a specific valuefield through lua in xls/csv, for example "valuefield_1" and get the value in the third third column, which would be 20. This is then saved as variable x in my lua script so that whenever I call variable x, it uses the value 20 until I update variable x with a different value by searching for a different valuefield value.
In my efforts to find a solution to this (seemingly simply) issue, all I came across are xls modules for lua, how to output files, how to do graphs, complicated stuff far beyond what I want to do.
Isn't there a simple way that I can have a line where it defines my variable by saying:
variable_x = value of the cell in the third column in the row of valuefield_x
so that I can simply set valuefield_x in my luascript according to what sort of valuefield I look for?
That's really all I need, I don't need to write xls/csv files or change anything in them. All I want is to accurately read specific cells in specific columns that are chosen by what "valuefield" I search for in the first column.
Can somebody tell me what the commands for that are?
I am not aware of a .xls file reader in Lua and in doubt writing one in pure Lua is feasible (although look at xlrd module in Python, might be easy to convert to Lua). In Python you can do that easily with win32com module so if you have option of using Python instead it is very easy to learn.
For .CSV file you would use open and read just as any other text file then parse with Lua pattern matching. If you post some where you show what you have tried (that's probably why you got so many downvotes) with these then I can post more specific answer.
Thanks for the answer, Schollii.
The problem was pretty much that I didn't even know how to begin with accessing, opening, editing or otherwise using Excel through lua, so any code example was pretty much useless. Thus I thought it best to describe what I required, rather than misdirecting with code snippets that dealt with entirely different things. (such as io.open and other things)
As always, after much - MUCH - research and browsing through 3 different manuals and rereading who knows how many irrelevant answers I came upon an answer that works for me. It's actually very simple, so I cannot begin to imagine how many people could've spared me the hours and hours of research with a five minutes answer. Let's hope that by providing a very thorough answer, I can ensure that other beginner like me who wish to do the same don't have to do the same amount of research. And yes, the answer is very basic, and yes, I'm also explaining things most people who know lua code don't need explained. This is for beginners like me.
First: Download "Lua for Windows"
http://code.google.com/p/luaforwindows/
Lua cannot - by itself - handle excel format, so instead you need to use the plugin LUACOM which is one of the modules installed through "Lua for Windows"
It also includes a nifty script editor whith which you can right-click your scriptfile, click edit script, and you have a nice interface to edit and TEST your script.
The actual script:
The first part of your script requires you to utilize Excel through luacom.
require('luacom')
excel = luacom.CreateObject("Excel.Application")
excel.Visible = true
a.The "require" line tells lua that it requires the module "luacom", to use the modules function for this lua script.
b. The second line through luacom opens an instance of Excel which is in the script referred to as "excel". This is necessary be able to target it with commands.
c. excel.Visible determines whether the open instance of excel can be seen by the user or whether its used invisible. Note how the "excel." reference points at the instance we called "excel" in line 2.
(Alternative)
It's also possible to target an existing instance of excel that has already been opened manually by the user by replacing the second line with:
excel = luacom.GetObject("Excel.Application")
If we use the alternative way, and target an already open excel program, we can already target all the values in the first sheet. If we however create a new instance of excel, we have to open the file we wish to read from.
fpath = "C:\\Examplepath\\Example.xlsx"
wb = excel.Workbooks:Open(fpath)
ws = wb.Worksheets("ImportantSheet1")
a. In the first line of this part, fpath determines the location of the xlsx file we wish to access. Note that "\" are used instead of "\".
b. We create the reference "wb" similar to the "excel reference in our first part of code. This one however opens a Workbook file (your excel file) at the location (fapth). Again, note how "excel." points the code at the excel instance we created earlier.
c. This line determines which sheet is to be opened in the just opened Workbook file. In this case, it's the sheet called "ImportantSheet1".
desired_name = "whatIseek"
for row=1, 4 do
for col=1, 4 do
local cell_location = excel.Cells(row, col).Value2
if cell_location == desired_name then
Value1 = excel.Cells(row, col +1).Value2
Value2 = excel.Cells(row, col +2).Value2
Value3 = excel.Cells(row, col +3).Value2
end
end
end
print(Value1)
print(Value2)
print(Value3)
a. desired_name sets up the value that we seek (in this case a string)
b. Line 2 and 3 determine that the following process is to be done for rows 1-4 and columns 1-4, though you don't have to call those "row" or "col".
c. The next line sets the value of the variable "current cell" to the value of the cell in excel at the position (x, y). You need to use ".Value2" (not ".Value") to in this command. So now our temporary variable has the cells value.
d. In the "if" command, we check if the current value of the cell is equal to the value we specified earlier as the "desired_name" which we seek.
e. If that is the case, "then" the next 3 lines set the Values 1-3 to the cells in the next columns in the same row. (So it "reads" from left to right the next values and saves them as our variable)
f. Finally, to check whether we actually have the values we want, we use the print command to view them when we execute the script. (This is, of course, not necessary to work with those values, this is merely here to check if this script works)

Simulate paste action in excel using vba

I am trying to populate an excel spreadsheet using VBA (is actually something different using a COM server but it is the same syntax). Thisis a report generated that I want to write in Excel for formatting and presentation purpose. CSV exports and other techniques are out of the equation because of the technology involved.
So, I am able to do it writing each value in each cell, but it is painfully slow, so, I decided I could write a bunch of values at once (let's say 250 records each time). So I store those values delimited by a carriage return and if I copy/paste that using VBA it works perfectly.
Problem is, I can't use the clipboard (as the report is executed many times simultaneously), so can I simulate the paste action (or some other similar) from a list of values in Excel without using the clipboard?
Thanks,
The fastest way to copy values in VBA I know is
Range("destrange") = Range("srcrange")
destrange and srcrange should be the same size. Also no formatting data etc. will be copied.
edit: here is something that could be usefull.
You can create an array of Variants and assign it to a range:
Dim v() As Variant
ReDim v(1 To 20, 1 To 10)
'Fill v
v(5, 5) = 42
'...
Range("a1:j20").Value = v

Resources