简单记录

DataTable相关

新建一个空的DataTable

New System.Data.DataTable

DataTable.Select()

使用 sql 语法筛选数据

dt.Select("[semployerName] like '*[*]*' or [semployerName] like '*''*' ")
Datatable Filtered_Results = dt.Select("[Column1] = '"+param_1+"' AND [Column2] = '"+param_2+"'").CopyToDataTable()

https://www.cnblogs.com/TeresaMu/p/12058559.html

https://docs.microsoft.com/zh-cn/dotnet/api/system.data.datatable.select?view=net-5.0

DataTable获取筛选后的某一字段

dt.Select("是否新增= '是'").Select( Function(row) row.Item("名称").ToString ).ToList()

筛选出来的是一个列表,可以转换成文本。

Join( dt.Select("是否新增= '是'").Select( Function(row) row.Item("名称").ToString ).ToList().ToArray, "、")

DataTable.Compute()

Compute (string? expression, string? filter);

用来计算值。

https://learn.microsoft.com/zh-cn/dotnet/api/system.data.datatable.compute?view=net-7.0

expression 解释
count() 求数量
sum(value) 求和
avg(value) 求平均
min(value) 求最小
max(value) 求最大
StDev(value) 统计标准偏差
Var(value) 统计方差
max(value)/sum(value) 其他计算

例: 计算 DataTable 中,【级别】为信息的条数。

级别 机器人
信息 UR015
错误 UR015
信息 UR015
警告 UR015
信息 UR015
dt.Compute(" Count(级别) ", " 级别 = '信息' ")

例:计算 DataTable 中,【资金类型】为代理费的 应划付金额 的总计。

资金类型 应划付金额
现金红利 517.97
代理费 13.71
交易净额 3,841.14
交易净额 2,300.00
dt.Compute(" Sum(应划付金额) ", " 资金类型 = '代理费' ")

【应划付金额】这一列不能为 String 型,String 型的会报错:Invalid usage of aggregate function Sum() and Type: Object.

把代码改成 dt.Compute(" Sum( Convert(应划付金额, 'System.Double' ) ) ", " 资金类型 = '代理费' ") 也不行,会报错:Syntax error in aggregate argument: Expecting a single column argument with possible ‘Child’ qualifier.

如果真的要实现,只能换方式:

dt.AsEnumerable().Where(Function(row) row.Item("资金类型").ToString = "代理费").Sum(Function(row) Convert.ToDouble( row.Item("应划付金额") ) )

或者是用 dt.Clone() 克隆表结构到 dtCloned,dtCloned.Columns(“应划付金额”).DataType = GetType(System.Decimal),然后把 dt 每一行的数据插入到 dtCloned,最后是使用 dtCloned.Compute 进行计算。(思路是这样,但是觉得太麻烦了

dt.Compute

DataTable.AsEnumerable().Where

筛选数据

dt.AsEnumerable().Where(Function(y) y.Item("semployerName").ToString.Contains("'") or y.Item("semployerName").ToString.Contains("*")).ToList()

https://forum.uipath.com/t/checking-special-characters-in-column-values-in-data-table/14599/2

DataTable.Clone()

克隆可创建具有与原始 DataTable 相同的结构的新 DataTable,但不复制任何数据(新 DataTable 将不会包含任何 DataRows)。

https://docs.microsoft.com/zh-cn/dotnet/api/system.data.datatable.clone?view=net-5.0

DataTable.Copy()

同时将结构和数据复制到新 DataTable 中,使用 Copy

给 DataTable 添加列(指定位置)

SetOrdinal(0)里面的 0 就是想添加到的位置。

dt.Columns.Add("列名").SetOrdinal(0)
dt.Columns.Add("列名", typeof(String)).SetOrdinal(0)

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/adding-columns-to-a-datatable

给 DataTable 添加列(指定位置、默认值)

Dim column As DataColumn
column = New DataColumn("日期")
column.DefaultValue = strBalanceDate

dtBankDataTable.Columns.Add(column)
column.SetOrdinal(0)

DataTable 调整列的顺序

将顺序调到第4列,计数从0开始

dt.Columns("ColumnName").SetOrdinal(4)

使用 Invoke Method 或者 Invoke Code 都可以实现

DataTable 判断是否存在某列

dt.Columns.Contains("列名")

DataColumn转list

( From row In dt.AsEnumerable() Select Convert.Tostring(row("列名")) ).ToList()

DataTable 去重1

Remove Duplicate Rows

DataTable 去重2

NameList = (From name in dtAllDataTable.Columns.Cast(of DataColumn) select name.ColumnName).ToArray

dvDataView = dtAllDataTable.DefaultView
    
dtAllDataTable = dvDataView.ToTable(True, NameList)

DataTable 列名去掉空格

TypeArgument : System.Data.DataColumn

DataTable 列名去掉空格

或者循环里面直接使用

item.ColumnName = item.ToString.Trim

DataTable 删除行1

使用 For Each ,

For Each row in dt.Select( "[文件名称] like '*' " )

dt.Select() 或者 dt.Rows 都可以。用 dt.Select() 主要是为了筛选数据,如果不需要的话,直接用 dt.Rows 即可。

TypeArgument 选择 System.Data.DataRow

Index 填写 intIndex

循环里面使用 Remove Data Row 。

DataTable 删除行

增加行的逻辑类似,只不过是把 Remove Data Row 换成 Add Data Row。

DataTable 删除行2

建一个列表 lstRowIndex 来存储需要删除的行数,New List(of integer),变量类型:System.Collections.Generic.List

使用 For Each Row in dt

Index 填写 intIndex

使用控件 Add To Collection,把需要删除的行加到 lstRowIndex。

遍历完成之后,使用 For Each item in lstRowIndex.ToArray.Reverse(),进行倒序删除。

DataTable 删除行2

DataColumn.Expression

https://learn.microsoft.com/zh-cn/dotnet/api/system.data.datacolumn.expression?view=net-6.0

LINQ

LINQ 概述

https://learn.microsoft.com/zh-cn/dotnet/visual-basic/programming-guide/concepts/linq/

https://docs.microsoft.com/zh-cn/dotnet/csharp/linq/

https://learn.microsoft.com/zh-cn/dotnet/api/system.linq?view=net-6.0

https://www.yiibai.com/linq/

https://forum.uipath.com/t/how-to-use-arithmetic-operator-using-linq/471768

LINQ 查询操作由以下三个操作组成:

  1. 获取数据源。
  2. 创建查询。
  3. 执行查询。
From num In numbers
Where num Mod 2 = 0
Select num

Lambda 表达式

Lambda 表达式是没有名称的函数,用于计算并返回单个值。 与命名函数不同,Lambda 表达式可以同时定义和执行。

在 LINQ 中,Lambda 表达式是许多标准查询运算符的基础。 编译器创建 Lambda 表达式来捕获基本查询方法(如 WhereSelectOrder ByTake While 等)中定义的计算。

(Function(num As Integer) num + 1)(6)

结果是:7

Dim add1 = Function(num As Integer) num + 1
Console.WriteLine(add1(3))
From stdnt In students
Where stdnt.Year = "Senior"
Select stdnt
students
.Where(Function(st) st.Year = "Senior")
.Select(Function(s) s)

获取压缩包

(From n In Directory.GetFiles(strFolderPath)
    Where n.ToLower.EndsWith(".zip") Or n.ToLower.EndsWith(".7z")
Select n).ToArray

去掉数组里面空的元素

myArray = myArray.Where(Function(s) Not String.IsNullOrEmpty(s)).ToArray()

数据类型

数据类型摘要

Visual Basic 类型 公共语言运行时类型结构 名义存储分配 取值范围
布尔值 Boolean 取决于实现平台 TrueFalse
Byte Byte 1 个字节 0 到 255(未签名)
Char(单个字符) Char 2 个字节 0 到 65535(未签名)
日期 DateTime 8 个字节 0001 年 1 月 1 日 0:00:00(午夜)至 9999 年 12 月 31 日晚上 11:59:59
十进制 Decimal 16 个字节 0 至 +/-79,228,162,514,264,337,593,543,950,335 (+/-7.9…E+28) †,不带小数点;0 至 +/-7.9228162514264337593543950335,小数点右侧 28 位小数; 最小的非零数字为 +/-0.0000000000000000000000000001 (+/-1E-28) †
Double(双精度浮点数) Double 8 个字节 对于负值,-1.79769313486231570E+308 至 -4.94065645841246544E-324 †; 对于正值,4.94065645841246544E-324 至 1.79769313486231570E+308 †
整数 Int32 4 个字节 -2,147,483,648 至 2,147,483,647(已签名)
Long(长整型) Int64 8 个字节 -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807 (9.2…E+18 †)(已签名)
Object Object(类) 32 位平台上的 4 个字节 64 位平台上的 8 个字节 Object 类型的变量中可存储任何类型
SByte SByte 1 个字节 -128 至 127(已签名)
Short(短整型) Int16 2 个字节 -32,768 至 32,767(已签名)
Single(单精度浮点) Single 4 个字节 对于负值,-3.4028235E+38 至 -1.401298E-45 †; 对于正值,1.401298E-45 至 3.4028235E+38 †
String(可变长度) String(类) 取决于实现平台 0 到大约 20 亿个 Unicode 字符
UInteger UInt32 4 个字节 0 到 4,294,967,295(未签名)
ULong UInt64 8 个字节 0 到 18,446,744,073,709,551,615 (1.8…E+19 †)(未签名)
User-Defined(结构) (继承自 ValueType 取决于实现平台 结构中的每个成员都有一个由其数据类型确定的范围,且该范围不依赖其他成员的范围
UShort UInt16 2 个字节 0 到 65,535(未签名)

Decimal 与 Double 的不同

一句话总结:Single 和 Double 只能用来做科学计算或者是工程计算,在商业计算中用 Decimal。

商业计算中,建议使用 Decimal,而不是使用 DoubleDecimal 数据类型为数字提供的有效位数最多。 它最多支持 29 个有效位数,并可表示超过 7.9228 x 10 ^ 28 的值。 它特别适用于需要大量数字但不允许舍入误差的计算(例如财务)。

Decimal 不是浮点数据类型。 Decimal 结构包含一个二进制整数值以及一个符号位和一个整数比例因子,该比例因子用于指定该值的小数部分。 因此,在内存中,Decimal 数字的表示形式比浮点类型(SingleDouble)更精确。

Convert.ToDouble( "66.144421" )
Double.Parse("17.89")

Convert.ToDecimal( 66.144421 )
Decimal.Parse("17.89")

参见:数据类型疑难解答 (Visual Basic)

浮点表达式不比较为等于

使用浮点数(单数据类型双数据类型)时,请记住,它们存储为二进制分数。 这意味着对于任何不是二进制分数的数量,它们无法提供准确的表示形式(采用 k / (2 ^ n) 的形式,其中 k 和 n 是整数)。 例如,0.5 (= 1/2) 和 0.3125 (= 5/16) 可以作为精确的值,而 0.2 (= 1/5) 和 0.3 (= 3/10) 只能是近似值。

由于这种不精确性,在使用浮点值时,不要指望获得准确的结果。 具体而言,理论上相等的两个值的表示形式可能略有不同。

比较浮点数量
1. 使用 System 命名空间中 Math 类的 Abs 方法计算其差值的绝对值。 2. 确定可接受的最大差值,这样,如果两个数量的差值不大于该值,则出于实用目的,你可以认为这两个数量相等。 3. 将差值的绝对值与可接受的差值进行比较。

Mod 运算符不返回准确的结果

由于浮点存储的不精确性,当至少有一个操作数为浮点时,Mod 运算符可能会返回意外的结果。

十进制数据类型不使用浮点表示形式。 在 SingleDouble 中不准确的许多数字在 Decimal 中是准确的(例如 0.2 和 0.3)。 尽管算术在 Decimal 中比在浮点中慢,但为了实现更好的精度,性能降低是值得的。

查找浮点数量的整数余数
1. 将变量声明为 Decimal。 2. 使用文本类型字符 D 将文本强制为 Decimal,以免其值对于 Long 数据类型来说太大。

举例:

dblVariable1 = Double.Parse("4.17")
dblVariable2 = Double.Parse("17.89")
dblVariable3 = dblVariable1 + dblVariable2

dblVariable4 = Double.Parse("22.06")

输出 dblVariable3 = dblVariable4 的结果为 False。

或者直接输出 Double.Parse("4.17") +Double.Parse("17.89") = Double.Parse("22.06") ,结果也是 False。

Double型比较

把相关变量换成 Decimal 型

decVariable1 = Decimal.Parse("4.17")
decVariable2 = Decimal.Parse("17.89")
decVariable3 = decVariable1 + decVariable2

decVariable4 = Decimal.Parse("22.06")

输出 decVariable3 = decVariable4 的结果为 True。

或者直接输出 Decimal.Parse("4.17") +Decimal.Parse("17.89") = Decimal.Parse("22.06"),结果也是 True。

Decimal型对比

在 19.10.4 版本的 Studio 上,输出 Double.Parse("4.17") +Double.Parse("17.89"),虽然日志里面是 22.06,但是直接 Debug 看 Message 的 in,其实是 22.060000000000002。但在 22.12.0 版本的 Studio 上,却是输出 22.060000000000002。

直接导致了我接手的一个流程,报错时,抛出的异常信息是:代理佣金管理界面表格中【发生额】合计:22.06,与【应划付金额】总计:22.06 不一致。都不好和业务老师解释,只能怪自己接手代码的时候没有注意到这里选用的数据类型。

Double型输出

运算符

And 运算符

逻辑与,两个都为真才为真。

AndAlso 运算符

短路的逻辑与

如果编译的代码可以根据一个表达式的结果绕过另一个表达式的计算,则称逻辑运算为短路。

如果第一个表达式的计算结果决定运算的最终结果,则无需计算第二个表达式,因为这无法改变最终结果。 如果绕过的表达式很复杂,或者涉及过程调用,短路可以提高性能。

逻辑与运算的话,两个表达式为真才为真,有一个不为真,则为假。

用 And,哪怕第一个表达式是假,也会去计算第二个表达式;

用 AndAlso,只要第一个表达式是假,就会直接返回假,不计算第二个表达式,如下表所示。

如果 表达式1 表达式2 结果 的值为
True True True
True False False
False (不计算) False

举个例子,假如在一个判断里面,我需要判断文件路径是否在某个字典里面,且还需要判断该路径是否在电脑本地存在。

dic.Keys.Contains("文件路径") AndAlso File.Exists( dic("文件路径").ToString )

这里用 AndAlso 就没问题,用 And 的话,在文件路径没有添加到字典的时候,File.Exists( dic("文件路径").ToString ) 就会报错,说这个key 不在字典里面。

所以,从方便、提高效率、避免错误的角度来说,用 AndAlso 会更好一些。

愿我不会再接手别人的代码。

Or 运算符

逻辑或,有一个为真则为真。

OrElse 运算符

短路的逻辑或

用 Or,哪怕第一个表达式是真,也会去计算第二个表达式;

用 OrElse,只要第一个表达式是真,就会直接返回真,不计算第二个表达式,如下表所示。

如果 表达式1 表达式2 结果 的值为
True (不计算) True
False True True
False False False

Xor 运算符

逻辑异,不短路的。

两个表达式之一的计算结果为 时,结果 才是

两个表达式同真同假,结果 皆为

如果 表达式1 表达式2 结果 的值为
True True False
True False True
False True True
False False False

IF

IIf(expr, truepart, falsepart)

参数描述 :   expr 必要参数。用来判断真伪的表达式。   truepart 必要参数,只能为文本。如果 expr 为 True,则返回这部分的文本。   falsepart 必要参数,只能为文本。如果 expr 为 False,则返回这部分的文本。

If( out_blIsCheckSuccess, "校验成功", "校验失败" )

IIF

IIf(expr, truepart, falsepart) 参数描述 :   expr 必要参数。用来判断真伪的表达式。   truepart 必要参数。如果 expr 为 True,则返回这部分的值或表达式。   falsepart 必要参数。如果 expr 为 False,则返回这部分的值或表达式。

IIf( out_blIsCheckSuccess, "校验成功", "校验失败" )

Note:使用 IIF 时,不管 expr 是真还是假,后面的 truePart 和 falsepart都会进行计算,虽然它只返回其中的一个。也就是 IIF 函数是不短路的

例如,如果 falsepart 产生一个被零除错误,那么程序就会发生错误,即使 expr 为 True。

它对每个表达式都会进行计算,如果某一项为 DBnull 则就会抛出异常,所以在进行非空判断时应该用 IF 的形式,而不应该用 IIF。

下面这个例子就会引发被零除错误。

intIndex = 100
IIf( out_blIsCheckSuccess, "校验成功", intIndex \ 0 )

https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.interaction.iif?view=net-7.0

String相关

字符串函数

https://learn.microsoft.com/zh-cn/dotnet/visual-basic/language-reference/functions/string-functions

https://learn.microsoft.com/zh-cn/dotnet/api/system.string?view=netframework-4.8#methods

输出”

""""

String 大写

str.ToUpper

String 小写

str.ToLower

String 转 Double 型

Convert.ToDouble("1.2")

转成两位精度小数

用 0 占位

Double.Parse("1.2").ToString("0.00")
Double.Parse("1").ToString("f")

去掉数字 0

Decimal.Parse("1.20").ToString("0.0#")

判断能不能转换为整数

Integer.TryParse("asd",0)

输出为:False

Integer.TryParse("123",0)

输出为:True

https://learn.microsoft.com/zh-cn/dotnet/api/system.int32.tryparse?view=net-6.0

转成百分比

Double.Parse("0.5").ToString("p")

https://docs.microsoft.com/zh-cn/dotnet/api/system.double.tostring?view=net-5.0

SecurePassword

获取或设置 SecureString 实例形式的密码。

secStrPassWord = New System.Net.NetworkCredential("","123456").SecurePassword

https://docs.microsoft.com/zh-cn/dotnet/api/system.net.networkcredential

Password

获取或设置与凭据关联的用户名的密码。

New System.Net.NetworkCredential("",pwd).Password

字符串加双引号

"test""Test" + """"

输出:test”Test”

String.Format

String.Format("银行名称:{0},账户类型:{1},文件名称:{2}", strBankName, strAccountType, strFileName)

https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.strings.format?view=net-6.0

将对象的值转换为字符串

String.Format补全0

Strings.Format(7, "000")

输出:007

也可以:https://docs.microsoft.com/zh-cn/dotnet/api/system.string.padleft?view=net-6.0

String 去掉前面的0

"0000abc".TrimStart("0".ToCharArray)

输出:abc

https://docs.microsoft.com/zh-cn/dotnet/api/system.string.trimstart?view=net-6.0

String 换行

"asdf"+ _ 
"dssffg"

输出:asdfdssffg

String 替换掉换行

str.Trim.Replace( Chr(10) , "").Replace( Chr(13) , "")
str.Trim.Replace( vbcrlf , "")

String 分割

Split(str, ",")
str.Split(","c)
str.Split({","})
str.split(CChar(","))
str.Split(Char.Parse(","))
str.Split(convert.ToChar(","))

https://learn.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/split-function

https://learn.microsoft.com/zh-cn/dotnet/api/system.string.split?view=net-7.0

用两个分隔符来分割

str.Split(","c, " "c)

去掉结果中包含空字符串的数组元素

str.Split( (",").ToArray, StringSplitOptions.RemoveEmptyEntries)

str.Split( (" "+",").ToArray, StringSplitOptions.RemoveEmptyEntries)

str.Split( {",", " "}, StringSplitOptions.RemoveEmptyEntries)

https://learn.microsoft.com/zh-cn/dotnet/api/system.stringsplitoptions?view=net-7.0

获取特定字符串在某字符串出现的位置

Instr( str, "特定字符串")

https://learn.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/instr-function

Substring 截取

从第六个字符开始,截取两个字符

str.Substring(6,2)

截第六个字符后的所有字符

str.Substring(6)

https://docs.microsoft.com/zh-cn/dotnet/api/system.string.substring?view=net-6.0

String 截取前四位

注意:不足 4 位也不会出错

Left(str, 4)
Strings.Left(str, 4)

String 截取后四位

注意:不足 4 位也不会出错

Right(str , 4)
Strings.Right(str , 4)

String 转 ASCII 码

每个字符串中的第一个字母的字符代码

Asc("A")

https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.strings.asc?view=net-6.0

ASCII 码转 String

Chr(65)

https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.strings.chr?view=net-6.0

替换匹配

System.Text.RegularExpressions.Regex.Replace(text, "\W","")

判断字符串是否为Null或者为空字符串

String.IsNullOrEmpty(str)

https://docs.microsoft.com/zh-cn/dotnet/api/system.string.isnullorempty?view=net-6.0

判断字符串是否为数字

.IsNumeric

"7".IsNumeric
IsNumeric( "7" )

选取器(Selectors)

关于选取器

<html omit:title='*新意*' />

带有通配符的选取器

<wnd app='notepad.exe' cls='Notepad' title='Untitled - Notepad' />
<wnd app='notepad.exe' cls='Notepad' title='*- Notepad' />
<wnd app='notepad.exe' cls='Notepad' title='Untitled?- Notepad' />

https://docs.uipath.com/studio/lang-zh_CN/docs/selectors-with-wildcards

动态选取器

MenuOption 为变量

<wnd app='notepad.exe' cls='Notepad' title='Untitled - Notepad' />
<ctrl automationid='MenuBar' idx='1' name='Application' role='menu bar' />
<ctrl name='' role='menu item' />

https://docs.uipath.com/studio/lang-zh_CN/docs/dynamic-selectors

正则表达式搜索

<wnd app='applicationframehost.exe' title='Calculator' /> 
<uia cls='LandmarkTarget' /> 
<uia automationid='CalculatorResults' name='Display is \d' role='text' matching:name='regex' />

https://docs.uipath.com/studio/lang-zh_CN/docs/regex-search

模糊搜索

<html title='*新意*' />
<webctrl id='depName' tag='SPAN' aaname='总部清算中心' matching:aaname='fuzzy' fuzzylevel:aaname='0.8' />
matching:<tag_name>=fuzzy 用于指定目标搜索标签,具体取决于 <tag_name> 值。
fuzzyLevel:<tag_name>=<numerical_value> 确定目标 <tag_name> 的匹配阈值。此选项支持 0 到 1 之间的数值,如下所示: 更趋近 0 - 返回的结果与 <tag_name> 的相似度较低 更趋近 1 - 返回的结果与 <tag_name> 的相似度较高

区分大小写的选取器

UiPath Selector 里面,属性默认是大小写敏感的,但是可以使用 casesensitive:<attribute-name>='false' 进行更改。

例:

<html app='chrome.exe' title='区分大小写的选取器' />
<webctrl parentid='content-container' tag='STRONG' aaname='RegEx' />

如果 RegEx 变成了 regex,那么上面的 Selector 就会报错,但是修改为下面这样,大小写不敏感,就不会报错了。

<html app='chrome.exe' title='区分大小写的选取器' />
<webctrl parentid='content-container' tag='STRONG' aaname='RegEx' casesensitive:aaname='false' />

https://docs.uipath.com/studio/lang-zh_CN/docs/case-sensitive-selectors

数据操作

新建数组

{"1", "2", "3"}
New String() {"1", "2", "3"}

新建一个List

New List(Of String)

实例化一个List

New List(Of String) From {"1", "2", "3"}

快速输出 list

先转为Array,然后再处理

Join( list.ToArray, "、" )
String.Join( ",", list)

https://learn.microsoft.com/zh-cn/dotnet/api/system.string.join?view=net-8.0

List 去重

list.Distinct().ToList

List 筛选

list1.Where( Function(y)  y.Contains("2") ).ToList

遍历 List 的时候删除 List 元素

正常的 for each in list,删除完 List 元素之后肯定会出错,对 list 再 ToList 一下就可以了。

list.ToList

或者 list 再 ToArray 一下

list.ToArray

甚至可以 ToArray 之后再翻转一下

list.ToArray.Reverse()

甚至还可以 ToArray 之后再翻转两次,再 ToList 一下

list.ToArray.Reverse().Reverse().ToList

判断 List 里面是否包含某字符

list.Contains(str)

https://learn.microsoft.com/zh-cn/dotnet/api/system.collections.generic.list-1.contains?view=net-6.0

判断 List 是否包含符合特定条件的数据

list1.Exists( Function(y)  y.Contains("2") )

两个 List 操作

list1 = New List(Of String) From {"1", "2", "3"}
list2 = New List(Of String) From {"1", "3","5","7"}

两个 List 取交集

FinalList = list1.Intersect(list2).ToList

FinalList 的值为 1、3

两个 List 取差集

FinalList = list1.Except(list2).ToList

FinalList 的值为 2

FinalList = list2.Except(list1).ToList

FinalList 的值为 5、7

两个 List 取并集

取并集是去重的

FinalList = list1.Union(list2).ToList

FinalList 的值为 1、2、3、5、7

两个 List 相加

Concat 是不去重的

FinalList = list1.Concat(list2).ToList

FinalList 的值为 1、2、3、1、3、5、7

新建字典

New Dictionary(Of String,Object) From{ {"异常结果收件邮箱",""}, {"发件邮箱账号密码凭据","发件邮箱账号密码"}, {"RobotWorkFolder","C:\Robots\asdf"} }

判断字典里面是否包含某个key

dic.ContainsKey("异常结果收件邮箱")

判断字典里面是否包含某个Value

Config.ContainsValue("发件邮箱账号密码")

遍历字典的键

for key in dic.Keys

遍历字典的值

for value in dic.Values

遍历字典

For Each 的 TypeArgument 选择 KeyValuePair

KeyValuePair

键:item.Key

值:item.Value

String 转 list

, 为分隔符,先按照分割符转为数组,再转为 list

str.Split( CChar(",") ).ToList

获取文本中的最后 15 行

用 chr(10) ,也就是换行来分割获取到的日志,然后获取最后的15条日志。

Split( strlogText, chr(10) ).TakeLast(15).ToList

把 strlogText 分割成之后数组,取前 15 条,再反转回去,接着转成 list

Split( strlogText, chr(10) ).Reverse().Take(15).Reverse().ToList

chr(13)是回车,把获取好的内容用回车拼接成文本

Join( Split( strlogText, chr(10) ).Reverse().Take(15).Reverse().ToArray, chr(13))

Skip 是跳过,把倒数 15 行前面的内容跳过

Split( strlogText, vbCrLf ).Skip( Split( strlogText, vbCrLf ).Count - 15 )

Math.Max 是返回两个值中的最大值

Split( strlogText, vbCrLf ).Skip( Math.Max(0, Split( strlogText, vbCrLf ).Count - 15) )

文本分割成数组

将字符串 strText 按照换行符进行分割,并返回一个包含分割后所有子字符串的数组,然后对于数组中的每个元素,都选取它本身作为结果。

From r In Split( strlogText,chr(10))
Select r

文本分割,获取符合指定条件的字符串数组

将字符串strErrorMsg按照换行符进行分割,并返回一个包含分割后所有子字符串的数组,然后选取其中所有包含字符串”新增代码”的子字符串,并返回一个新的数组,其中只包含符合条件的子字符串。

From r In Split( strErrorMsg,chr(10))
Where r.Contains("新增代码")
Select r

Base64 转 Byte Array

Convert.FromBase64String( strImageBase64 )

Byte Array 保存为图片

File.WriteAllBytes( strImgPath, arrByteArray )

生成一个随机数

范围是 0 到 9

Cint( Rnd()*9 )

范围是 10 到 100

New Random().Next(10, 100)

范围是1到15

New Random(DateTime.Now.Millisecond).Next(1, 15)

邮件相关

内容 代码
发件时间 mail.Headers(“Date”)
邮件时间 mail.DateAsDateTime
收件时间 mail.Headers(“Recieved”)
发件地址 mail.From.Address
邮件标题 mail.Subject.ToString
附件数量 mail.Attachments.Count
邮件正文 mail.Body

邮件正文里面带图片

strMailBody = "邮件里面的文字信息"

byteArray = File.ReadAllBytes(strScreenshotPath)
strPicBase64 = Convert.ToBase64String(byteArray)
strPicHtml = "<img src=data:image/jpeg;base64,"  + strPicBase64 + ">"

"<html><body>"+ strMailBody + strPicHtml +"</body></html>"

调整邮件正文内容的 css

需要勾选 IsBodyHtml ,或 IsBodyHtml 为 True

"<STYLE type=text/css>
       font {
            font-size: 22px !important;
        }
</STYLE><font>邮件正文内容</font>"

邮件里面带上表格

需要勾选 IsBodyHtml ,或 IsBodyHtml 为 True

如果是有 Create HTML Content 这个控件,则可以使用这个控件。

若是没有,则使用遍历表头+表的内容组合出 DataTable 的 Html

163 邮箱配置

163邮箱配置

关闭SSL验证

System.Net.ServicePointManager.ServerCertificateValidationCallback =
Function(se As Object,
cert As System.Security.Cryptography.X509Certificates.X509Certificate,
chain As System.Security.Cryptography.X509Certificates.X509Chain,
sslerror As System.Net.Security.SslPolicyErrors) True

日期时间相关

https://learn.microsoft.com/zh-cn/dotnet/api/system.datetime

输出当前时间

yyyy:年; MM:月; dd:日;

hh:小时,12 小时制。如果是下午三点,会输出 03; HH:小时,24 小时制。如果是下午三点,会输出 15; mm:分 ss:秒

Now.ToString("yyyyMMdd hh:mm:ss")

输出:20221216 10:06:58

其实 Now 就是 DateTime.Now,为了方便,省略了。

DateTime.Now.ToString("yyyyMMdd hh:mm:ss")

输出:20221216 10:06:58

输出结果是一样的。

时间转为当地时间

DateTime.UtcNow.ToLocalTime()

https://learn.microsoft.com/zh-cn/dotnet/api/system.datetime.tolocaltime?view=net-7.0

获取日期的星期

Now.DayOfWeek

输出:Sunday

https://learn.microsoft.com/zh-cn/dotnet/api/system.datetime.dayofweek?view=net-6.0


Now.ToString("dddd")

输出:Sunday


Now.ToString("ddd")

输出:Sun


Now.ToString("dddd",New Globalization.CultureInfo("zh-cn"))

输出:星期日


Now.ToString("ddd",New Globalization.CultureInfo("zh-cn"))

输出:周日


Weekday(Now,vbSunday)

Weekday(date, [firstdayofweek])

Part 说明
date 必需。 可以表示日期的 Variant数值表达式字符串表达式或任意组合。 如果 date 包含 Null,则返回 Null
firstdayofweek 可选。 指定一周的第一天的常量。 如果不指定,则假定为 vbSunday

设置

firstdayofweek 参数具有以下设置:

常量 说明
vbUseSystem 0 使用 NLS API 设置。
vbSunday 1 周日(默认)
vbMonday 2 星期一
vbTuesday 3 星期二
vbWednesday 4 星期三
vbThursday 5 星期四
vbFriday 6 星期五
vbSaturday 7 星期六

返回值

Weekday 函数可以返回以下任一值:

常量 Description
vbSunday 1 星期日
vbMonday 2 星期一
vbTuesday 3 星期二
vbWednesday 4 星期三
vbThursday 5 星期四
vbFriday 6 星期五
vbSaturday 7 星期六

https://learn.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/weekday-function

获取这周几的日期

获取周一的日期

Now.AddDays(1 - Weekday(Now,vbMonday) ).ToString("yyyyMMdd")

周日的话,把 vbMonday 改成 vbSunday

Now.AddDays(1 - weekday(now,vbSunday)).ToString("yyyyMMdd")

获取某年某月的天数

DateTime.DaysInMonth(2023, 2)

输出:28

https://learn.microsoft.com/zh-cn/dotnet/api/system.datetime.daysinmonth?view=net-6.0

对日期进行加减年月日

加一年:.AddYears(-1) 加一月:.AddMonths(-1) 加一天:.AddDays(-1)

减一年:.AddYears(+1) 减一月:.AddMonths(+1) 减一天:.AddDays(+1)

Now.AddMonths(+1).ToString("yyyyMMdd")

输出:20230116

字符串转为DateTime

转换为 DateTime 变量,一般是够用的

Convert.ToDateTime("2022/05/25")
DateTime.Parse("2022/05/25")

如果格式特别奇怪的话,可以使用 DateTime.ParseExact:

DateTime.ParseExact( "Tue May 25 18:11:19 CST 2022", "ddd MMM dd HH:mm:ss CST yyyy", Nothing)
DateTime.ParseExact( "Tue May 25 18:11:19 CST 2022", "ddd MMM dd HH:mm:ss CST yyyy", New System.Globalization.CultureInfo("en-US") )

将日期时间的字符串转换为 DateTime

strReceiptime = "Wed, 15 Dec 2021 15:00:04 +0800"
format = "ddd, dd MMM yyyy HH:mm:ss zzz (CST)"
strReceiptime = "Wed, 15 Dec 2021 15:00:04 +0800 (CST)"
format = "ddd, dd MMM yyyy HH:mm:ss zzz (CST)"
DateTime.ParseExact(strReceiptime, format, System.Globalization.CultureInfo.InvariantCulture)

https://docs.microsoft.com/zh-cn/dotnet/api/system.datetime.parseexact

https://blog.csdn.net/bigheadsheep/article/details/12013267

判断能否把字符串转化为DateTime

DateTime.TryParse

直接进行转化的判断

DateTime.TryParse("2022/08/05", dtmdateValue)

DateTime.TryParseExact

提供日期格式的转化判断

DateTime.TryParseExact("20220805", "yyyyMMdd", Nothing, System.Globalization.DateTimeStyles.None, dtmdateValue)

Subtract

输出时间差

Time1 = DateTime.now()
Time2 = DateTime.now()

System.TimeSpan diff1 =Time1.Subtract(Time2)

System.TimeSpan diff2 =Time2-Time1

https://docs.microsoft.com/zh-cn/dotnet/api/system.datetime.subtract?view=net-6.0

Subtract(DateTime) 返回一个新的 TimeSpan,从此实例的值中减去指定的日期和时间。
Subtract(TimeSpan) 返回一个新的 DateTime,从此实例的值中减去指定持续时间。

DateDiff

输出时间差,DateInterval.Second是秒数,DateInterval.Minute 是分钟数,DateInterval.Day 是日期数

DateDiff(DateInterval.Minute, Time1,Time2)

https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.dateandtime.datediff?view=net-6.0

https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.dateinterval?view=net-6.0

TimeSpan 结构

https://docs.microsoft.com/zh-cn/dotnet/api/system.timespan?view=net-6.0

TimeSpan(Int32, Int32, Int32) TimeSpan 结构的新实例初始化为指定的小时数、分钟数和秒数。
TimeSpan(Int32, Int32, Int32, Int32) TimeSpan 结构的新实例初始化为指定的天数、小时数、分钟数和秒数。
TimeSpan(Int32, Int32, Int32, Int32, Int32) TimeSpan 结构的新实例初始化为指定的天数、小时数、分钟数、秒数和毫秒数。
TimeSpan(Int64) TimeSpan 结构的新实例初始化为指定的刻度数。

Delay 500 毫秒

UiPath_Delay500毫秒

00:00:00.500

New TimeSpan(0, 0, 0, 0,500)

TimeSpan.FromSeconds( 0.500 )

Delay 5 秒

00:00:05

New TimeSpan(0, 0, 5)

New TimeSpan(0, 0, 0, 5)

TimeSpan.FromSeconds( 5 )

https://learn.microsoft.com/zh-cn/dotnet/api/system.timespan.fromseconds?view=net-7.0

Delay 1 分钟

00:01:00

New TimeSpan(0, 1, 0)

TimeSpan.FromMinutes( 1 )

https://learn.microsoft.com/zh-cn/dotnet/api/system.timespan.fromminutes?view=net-7.0

获取当前是第几季度

DatePart( "q", Now() )

文件/文件夹相关

获取某个文件夹下的所有文件夹

Directory.GetDirectories("C:\Robots\asdf")

获取某文件夹下的所有 .csv 文件

Directory.GetFiles("C:\Robots\asdf", "*.csv")

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.directory.getfiles?view=net-6.0

获取某文件夹下的所有 .xls 文件的数量

Directory.GetFiles("C:\Robots\asdf","*.xls").Count

获取某文件夹下,包含子文件夹的所有文件

Directory.GetFiles( in_strInputPath, "*" , SearchOption.AllDirectories )

SearchOption

AllDirectories 1 在搜索操作中包括当前目录和所有它的子目录。 此选项在搜索中包括重解析点,比如安装的驱动器和符号链接。
TopDirectoryOnly 0 仅在搜索操作中包括当前目录。

获取某文件夹下,包含子文件夹的文件数量

Directory.GetFiles( in_strInputPath,"*", searchOption.AllDirectories).Count

获取某文件夹下,所有 .dat 或 .gz 文件

Directory.GetFiles(in_strInputPath, "*" ).Where(Function(s) s.EndsWith(".dat") or s.EndsWith(".gz") )

获取某文件夹下,包含子文件夹的所有的文件夹

Directory.GetDirectories(in_strInputPath,"*", searchOption.AllDirectories)

删除某文件夹下,所有空文件夹

  1. Directory.GetDirectories(in_strInputPath,"*", searchOption.AllDirectories),遍历所有文件夹;
  2. 然后Directory.GetFiles( item,"*", searchOption.AllDirectories).Count = 0, 判断文件夹是否为空,如果文件数量为 0,则把文件夹路径添加到待删除文件列表;
  3. 最后待删除文件列表去重,遍历列表,删除文件夹。

选择文件(SelectFile)

如果是需要自定义文件的筛选 ,比如说要筛选出 .nupkg 的文件,Filter 就填写

nupkg (*.nupkg)|*.nupkg

例如,如果只想选择 PDF 文件,则筛选器应类似于 PDF files (*.pdf)|*.pdf

如果需要多种图像文件类型以及所有文件,则筛选器应类似于 Image files (*.bmp, *.jpg)|*.bmp;*.jpg|All files (*.*)|*.*

https://docs.uipath.com/activities/lang-zh_CN/docs/select-file

获取文件大小(字节数)

code

fileSize = FileLen(filePath).ToString

文件重命名

code

FileSystem.Rename(oldPathName,newPathName)

文件压缩

strSourcePath, 压缩的目录路径;strZipFilePath, 要生成压缩包的所在路径。strZipFilePath 貌似不能在 strSourcePath 里面。

code

System.IO.Compression.ZipFile.CreateFromDirectory(strSourcePath, strZipFilePath)

设置压级别、压缩包不包含基目录

System.IO.Compression.ZipFile.CreateFromDirectory(System.IO.Compression.CompressionLevel.Fastest, False)

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.compression.zipfile.createfromdirectory?view=net-5.0

文件解压

将指定 zip 压缩包中的所有文件都解压缩到文件系统的一个目录下。

System.IO.Compression.ZipFile.ExtractToDirectory(strZipFilePath,strUnzipFilePath,System.Text.Encoding.Default)

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.compression.zipfile.extracttodirectory?view=net-5.0

获取文件路径

Path.GetDirectoryName("C:\Robots\港股通权限补报送\港股通权限补报送_日志表.xlsx")

运行结果:C:\Robots\港股通权限补报送

获取文件扩展名

Path.GetExtension("C:\Robots\港股通权限补报送\港股通权限补报送_日志表.xlsx")

运行结果:.xlsx

获取文件名

Path.GetFileName("C:\Robots\港股通权限补报送\港股通权限补报送_日志表.xlsx")

运行结果:港股通权限补报送_日志表.xlsx

获取文件名,不带扩展名

Path.GetFileNameWithoutExtension("C:\Robots\港股通权限补报送\港股通权限补报送_日志表.xlsx")

运行结果:港股通权限补报送_日志表

获取文件名所在的根目录

Path.GetPathRoot("C:\Robots\港股通权限补报送\港股通权限补报送_日志表.xlsx")

运行结果:C:\

当前用户的临时文件夹的路径

Path.GetTempPath

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.path.gettemppath?view=net-6.0&tabs=windows

环境相关

获取当前文件夹路径

Environment.CurrentDirectory

字符串组合成路径

Path.Combine(Environment.CurrentDirectory,"Data")

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.path.combine?view=net-5.0

文件在远程桌面的路径

Path.Combine("\\tsclient\", in_Config("RobotWorkFolder").ToString.Replace(":\","\"), strFileName)

获取文件夹里面最新的一个文件

Directory.GetFiles(Environment.CurrentDirectory,"Exceptions_Screenshots\").OrderByDescending(Function(d) New FileInfo(d).CreationTime)(0)

Windows 系统相关

自动登录Windows

免费:https://www.logonexpert.com/freeautologon/

付费:LogonExpert(可试用),配置好之后就可以自动登录Windows系统了

命令行使用:

"C:\Program Files\Softros Systems\LogonExpert\le.exe" -logon username [password][domain]

详细信息请参考:https://www.logonexpert.com/help/command-line/

如果有域名的话,一定要加上域名。

也可以在LogonExpert Administrator 配置好,然后直接使用

"C:\Program Files\Softros Systems\LogonExpert\le.exe" -logon *

启动进程

WorkingDirectory:如果未设置该属性,则默认工作目录为 %SYSTEMROOT%\system32。

UiPath 的控件 Open Application 打开应用,除非指定工作目录,否则都是默认使用 %SYSTEMROOT%\system32

NewProcess = New System.Diagnostics.Process

NewProcess.StartInfo.CreateNoWindow = False '是否创建窗口
NewProcess.StartInfo.FileName = '文件名称
NewProcess.StartInfo.Arguments = " " + argInstrArguments '参数

NewProcess.StartInfo.WorkingDirectory = '工作目录
NewProcess.StartInfo.UseShellExecute = '是否使用shell来执行

NewProcess.Start() '启动进程
NewProcess.WaitForExit() '等待进程退出

System.Diagnostics.Process.Start 用法

https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=net-6.0

打开文件管理器

System.Diagnostics.Process.Start("explorer.exe")

打开文件管理器,指定路径

System.Diagnostics.Process.Start("explorer.exe", "C:\Users\lbj\Documents\ChromeDownloads")

打开文件管理器,选中指定文件

System.Diagnostics.Process.Start("explorer.exe", "/select,"+ "C:\Users\lbj\Documents\ChromeDownloads\031002100311_43538867.pdf" )

打开远程桌面的文件管理器,指定路径

Argument:文件夹路径

FileName:”C:\Windows\explorer.exe”

Selector:```


![Uipath打开远程桌面的文件管理器,指定路径](https://img.lbjheiheihei.xyz/img/20220416_Uipath打开远程桌面的文件管理器,指定路径.png?imageView2/0/format/webp/interlace/1/q/75 "Uipath打开远程桌面的文件管理器,指定路径")

### 设置已中断会话时间限制

为防止流程在系统启动后处于锁屏状态,通过设置 ”**已中断会话时间限制**“ 来让会话注销,达到每次进去之后都创建一个新的远程链接。

在运行中输入:**gpedit.msc** 打开本地组策略编辑器

计算机设置->管理模板->Windows 组件->远程桌面服务->远程桌面会话主机->会话时间限制

双击打开“**设置已中断会话的时间限制**”,选中“**已启用**”,“结束已断开连接的会话”设置为“**1分钟**”

### 设置Windows Server登录时禁止自动启动服务器管理器

[https://blog.csdn.net/allway2/article/details/103940157](https://blog.csdn.net/allway2/article/details/103940157)

## 输入法相关

### 切换为英文输入法

安装依赖 LanguageChange,然后使用控件Language Change Activity 切换成英文

![](https://img.lbjheiheihei.xyz/img/20220810_切换为英文输入法.png?imageView2/0/format/webp/interlace/1/q/75 "切换为英文输入法")

## 鼠标相关

### 鼠标滚轮上下滑动

安装依赖包:ScrollActivity

### 鼠标移动到具体的元素位置

控件:Hover

### 鼠标循环滚动到具体的元素位置

循环 + 控件:Hover

### 鼠标移动指定的距离

Uipath 实现起来挺麻烦的,cmd 使用工具 [nircmd](http://www.nirsoft.net/utils/nircmd.html) 可以实现,但是 nircmd 会报毒(实测火绒、360)。

鼠标位置相对移动  movecursor [X] [Y]

move the mouse cursor. The **[X]** and **[Y]** parameters specifies the number of pixels to move. 

Example: movecursor 100 100

```shell
nircmdc movecursor 100 100

注:可以使用 PowerShell 实现

Http请求

安装依赖包 UIPath.WebAPI.Activities

短信(验证码)相关

使用短信猫、双卡助手(安卓)、短信转发器 (安卓)、 IFTTT(安卓)、Tasker(安卓)、快捷指令(iOS 半自动)、来转发短信。

可以查看影刀的文档

也可以试试:sms_forwarding

Excel相关

将列索引转换为列字母

UiPath.Excel.Helpers.ExcelUtilities.ConvertColumnIndexToColumnLetter(number)

将列字母转换为列索引

UiPath.Excel.Helpers.ExcelUtilities.ConvertColumnLetterToColumnIndex("A")

Write Range 后的数据不对

使用 Workbook 的 Write Range,不要使用 Excel 的 Write Range。前者的单元格格式是文本,后者则不一定。

Excel 去重

使用 Remove Duplicates Range,如果数据是A到Z列,则范围填写A:Z

无法导入 UiPath 生成的 Excel 文件

SAP或者别的应用,可能是因为 UiPath 生成的 Excel 文件不带有用户信息?

需要信任一下才能导入 Excel 文件

设置_受信任位置

Write Range报错: Cannot write to the target range because it has hidden rows. Remove any filters or unhide rows and try again.

打开的 Excel 里面的 Sheet 有隐藏的行或者列,无法使用 Excel 的 Write Range,但是可以用 Workbook 的 Write Range

一个一个cell填写数据特别慢

  1. Excel Scope 取消勾选 Save changes,填写完成后使用控件 Save Workbook
  2. 打开excel之后,先按下滚动条,滑动一下

Excel 自动填写数据

控件:Auto Fill Range

Delete Range

range填写 “A:Z”,代表删掉 A 到 Z 列的数据。

Excel 在表格里面筛选数据

前提:已有 excel 文件,里面的数据已经设置好筛选

使用控件:Filter Table,疑似对表有用,对透视表无用。

控件 Filter Table

别的都还好填写,但是 TableName 真的不知道在哪。

获取TableName

https://docs.uipath.com/activities/lang-zh_CN/docs/table-functions

第三方控件

官方的控件不够用的话,可以使用

BalaReva.Excel.Activities

表格转置:https://marketplace.uipath.com/listings/transpose-datatable9373/versions

VBA相关

UiPath 运行VBA,前置操作

Excel:

如果报错 Invoke VBA: 不信任到 Visual Basic Project 的程序连接,那么去 Excel 的 文件-> 选项,找到信用中心,点击信用中心设置。

接着找到宏设置, 在开发人员宏设置里面勾选「启用所有宏 」、「信任对VBA工程对象模型的访问」

WPS:

设置1、开发工具->宏安全性->可靠发行商, 勾选信任对于”Visual Basic 项目”的访问。

设置2、文件->选项->信任中心,勾选【启用宏后自动添加为受信任的文档】。

VBA 删除Sheet页

delSheet.txt 的内容:

Sub Deletesheet(sheetName)
Sheets(sheetName).Delete
End Sub

想删除的是 Sheet2

VBA 删除Sheet

Function DeleteSheet(in_StrFilePath, in_StrSheetName As String) As String

Application.DisplayAlerts = False '禁止弹窗
Application.ScreenUpdating = False '禁止显示

On Error GoTo Myerr '异常处理
Dim Wb_Root As Workbook

Set Wb_Root = Workbooks.Open(in_StrFilePath, 0)
'初始化结束

Wb_Root.Sheets(in_StrSheetName).Delete


Wb_Root.Save
Wb_Root.Close

Myerr:
DeleteSheet = Err.Description
Application.DisplayAlerts = True
Application.ScreenUpdating = True

End Function

VBA 删除C列为空的行

Worksheets("指数转化表").Columns("c:c").SpecialCells(xlCellTypeBlanks).EntireRow.Delete

若C列没有空的数据,会报错【未找到单元格】。

VBA 删除指定范围的行

Worksheets("指数转化表").Range("H20:N1171").EntireRow.Delete

VBA 从最后一行删到指定行

Sheet<指数转化表>, 从最后一行开始删数据,删到第20行

Dim i As Integer

For i = Worksheets("指数转化表").UsedRange.Rows.Count To 20 Step -1
	Worksheets("指数转化表").Rows(i).Delete
Next i

VBA 从指定行开始删数据

Sheet<指数转化表>, 从20行开始删数据

Worksheets("指数转化表").UsedRange.Offset(20).Delete

注:对表不可用,会报错【不允许此操作,因为它会移动工作表上表格中的单元格】

VBA 粘贴数据

Wb_Root.ActiveSheet.Paste

VBA 自动调整所选列列宽

调整 i 列的列宽

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
ActiveSheet.Range("i:i").EntireColumn.AutoFit
End Sub

VBA 打开 Excel

Function OpenExcel(in_StrFilePath As String)

Application.DisplayAlerts = False '禁止弹窗
Application.ScreenUpdating = False '禁止显示

On Error GoTo ErrorHandler '异常处理
    
Dim Wb As Workbook

Set Wb = Workbooks.Open(in_StrFilePath, 0)
'初始化结束

Application.Workbooks(wb).Activate '测试异常的情况

Wb.Save
Wb.Close
    
Exit Function '正常运行完成,退出 Function

ErrorHandler:
OpenExcel = "运行错误,错误号:" & Err.Number & ",错误信息:" & Err.Description
Application.DisplayAlerts = True
Application.ScreenUpdating = True

End Function

Err 对象

Error对象

   
Description 设置或返回一个描述错误的字符串
Number (缺省属性)设置或返回指定一个错误的值
Source 设置或返回产生错误的对象的名称
Clear 清除当前所有的Err对象设置
Raise 产生一个运行期错误

https://docs.microsoft.com/zh-cn/office/vba/api/excel.error

https://learn.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/err-object

https://learn.microsoft.com/zh-cn/office/vba/language/reference/user-interface-help/error-statement

Sub 和 Function 的区别

可以简单的理解为 ,Sub 是过程,没有返回值。Function 是函数,有返回值。

https://learn.microsoft.com/zh-cn/office/vba/language/concepts/getting-started/calling-sub-and-function-procedures

SQL

MySQl 配置 ODBC

执行 sql 前,需要安装 mysql-connector-odbc (32位的),安装完成后打开ODBC数据源(32位),选择用户DSN,随后点击添加。

选择 MySQL ODBC Unicode Driver(旧版本只有 MySQL ODBC Driver)

ODBC新建数据源

输入DNS名字以及描述、MySQL数据库的IP地址与端口,点击ok。点击 Details 展开,设置中文字符集。

OBDC设置

清空一个表

TRUNCATE TABLE 表名;

把一个表的数据去重放入另一个表

vcp_all 表不设置主键,vcp_distinct 表设置主键。

如果 all 表有,distinct 表没有,则会把数据插入到 distinct 表;

如果 all 表有,distinct 表也有,则会把 distinct 表的数据更新;

replace INTO vcp_distinct select * from vcp_all;

正则

正则表达式构建器

https://docs.uipath.com/activities/lang-zh_CN/docs/regex-builder-wizard

日期是否是yyyy/MM/dd

^[12]\d{3}/(?:0[1-9]|1[0-2])/(?:0[1-9]|[12][0-9]|30|31)$

获取数字

用正则把非数字的字符去掉

System.Text.RegularExpressions.Regex.Replace( str, "[^0-9]+", "")

获取英文

用正则把非英文的字符去掉

System.Text.RegularExpressions.Regex.Replace( str, "[^A-Za-z]+", "")

获取中文

用正则把非中文的字符去掉

System.Text.RegularExpressions.Regex.Replace( str, "[^\u4e00-\u9fa5]]+", "")

判断字符串中是否含有5个下划线

System.Text.RegularExpressions.Regex.Matches(str,"_").Count=5

匹配日期(年-月-日)

匹配(年-月-日)格式日期

([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8])))

匹配数字+英文

[A-Za-z0-9]+$

匹配数字+英文(至少是五位)

[A-Za-z0-9]+${5,}

匹配数字+英文+()()_(至少是五位)

[A-Za-z0-9\+\-()\(\)]+${5,}

匹配中文

pattern: “[\u4e00-\u9fa5]+”

匹配非中文

[^\u4e00-\u9fa5]

SAP

启用 SAP GUI 脚本编写

启用 SAP GUI 脚本编写

或者看 Uibot 的 https://docs.uibot.com.cn/guide/d1/ch004.html?version=0.6422463797095322#sap%E7%A8%8B%E5%BA%8F

支持的 SAP WinGUI 元素

https://docs.uipath.com/studio/lang-zh_CN/docs/supported-sap-wingui-elements#sap-alv-table

Bat脚本(cmd命令行)

在远程控制的使用可以使用 bat 脚本来实现某些功能

修改cmd窗口编码为UTF-8

chcp 65001

创建虚拟磁盘

把 C:\O32_d 映射到 H 盘

@echo off
C:\Windows\System32\Subst H: C:\O32_d
Pause

删除虚拟盘

取消 H 盘的映射

@echo off
C:\Windows\System32\Subst H: /d
Pause

杀进程

以 UiPath.Executor 为例,可以在任务管理器的详细信息里面找到执行的程序名称。

taskkill /f /t /im UiPath.Executor.exe

7Zip 压缩文件

a:将文件添加到压缩档案中 b:测试压缩或解压算法执行时的 CPU 占用 d:从压缩档案中删除文件 e:将压缩档案中的所有文件解压到指定路径,所有文件将输出到同一个目录中 h:计算文件的哈希值 i:显示有关支持格式的信息 l:列出压缩档案的内容 rn:重命名压缩档案中的文件 t:测试压缩档案的完整性 u:更新要进入压缩档案中的文件 x:将压缩档案中的所有文件解压到指定路径,并包含所有文件的完整路径

"C:\Program Files\7-Zip\7z.exe" a 压缩包路径 压缩文件路径

7Zip 解压文件

-o和解压路径不要用空格分开

"C:\Program Files\7-Zip\7z.exe" x 压缩包路径 -o解压路径

WinRAR 压缩文件

压缩文件的一般命令行命令语法为:

WinRAR A [-参数] <压缩文件> [文件] [@文件列表]

例如说,您希望添加文件 LETTER.TXT 到压缩文件 LETTERS.RAR ,请输入:

WinRAR A LETTERS.RAR LETTER.TXT

建议是使用

WinRAR A -ep1 LETTERS.RAR LETTER.TXT

添加文件夹 “c:\latest data” 到压缩文件 Info.rar 中

WinRAR a Info.rar "c:\latest data"

WinRAR 解压文件

解压压缩文件 Info.rar 到文件夹 d:\data

WinRAR x Info.rar d:\data\

xcopy 复制文件

把 D:\666 文件夹下面的所有文件和文件夹复制到E:\777,其中包含空的文件夹,不提示是否要覆盖现有目标文件。

xcopy "D:\666" "E:\777" /s /e /y

把 D:\666 文件夹下面的 *_compare_result.xlsx 复制到E:\777,不提示是否要覆盖现有目标文件。

xcopy "D:\666\*_compare_result.xlsx" "E:\777" /y

https://docs.microsoft.com/zh-cn/windows-server/administration/windows-commands/xcopy

参数 说明
/f 复制时显示源和目标文件名。
/d [:MM-DD-YYYY] 仅复制指定日期或之后更改的源文件。 如果未包含 MM-DD-YYYYY 值,xcopy则复制比现有目标文件更新的所有源文件。 此命令行选项允许更新已更改的文件。
/s 复制目录和子目录,除非它们为空。 如果省略 /sxcopy 可在单个目录中工作。
/e 复制所有子目录,即使它们为空也是如此。 将 /e/s/t 命令行选项配合使用。
/exclude:FileName1[+[FileName2]][+[FileName3] ( ) ] 排除文件列表。 必须至少指定一个文件。 每个文件将包含搜索字符串,其中每个字符串位于文件中的单独行上。 当任一字符串与要复制的文件绝对路径的任何部分匹配时,将排除该文件被复制。 例如,指定字符串 obj 将排除目录 obj 下的所有文件或 扩展名为 .obj 的所有文件。
/y 禁止提示确认要覆盖现有目标文件。
/j 在不缓冲的情况下复制文件。 建议用于非常大的文件。 此参数已在 Windows Server 2008 R2 中添加。

移动鼠标

rundll32 user32.dll,SetCursorPos

等待 10 秒

@echo off
timeout /t 10 /NOBREAK

https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/timeout

等待 5 秒 (ping 127.1 的方式)

这个等待时间不太准确

ping 127.1 -n 5 > nul

PowerShell

PowerShell 移动鼠标一段距离(X轴)

使用控件:Invoke Power Shell

勾选:IsScript

Paramenters:MoveX、speed

参数说明:MoveX 为 X 轴要移动的距离,可以为正,可以为负;speed 为移动的速度,实际为 Sleep 的毫秒数。

实际效果:在当前位置上,鼠标在X轴移动一段距离

Param(
[Parameter(Mandatory=$true)] [int32]$MoveX,   # X轴要移动的距离,可以为正,可以为负
[Parameter(Mandatory=$true)] [Int32]$speed  # 移动的速度,实际为 Sleep 的毫秒数
)

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# $MoveX = -100   # X轴要移动的距离

$MoveCount = 0  # 移动的次数

while($MoveX -gt 0) # 遍历到 MoveX 为 0。-ge :大于等于,如果 MoveX 大于等于0,则进入循环
{
    $MoveX = $MoveX-1
	$x = [Windows.Forms.Cursor]::Position.X+1   # 鼠标当前 X 轴的位置 +1
	$y = [Windows.Forms.Cursor]::Position.Y   # 鼠标当前 Y 轴的位置
	
	$MoveCount= $MoveCount +1
	if ($MoveCount -eq 10)  # 如果移动的次数等于10,则随机变动一下位置,可以去掉,感觉也不太好用。
        {
			$RandomX = Get-Random -Minimum -1 -Maximum 1  # 随机数,最小为-1,最大为1
			$RandomY = Get-Random -Minimum -1 -Maximum 1  # 随机数,最小为-1,最大为1
            $x = $x + $RandomX
			$y = $y + $RandomY
			$MoveCount = 0  # 移动的次数归零
         }
	
	[Windows.Forms.Cursor]::Position = new-object Drawing.Point $x,$y
	Start-Sleep m $speed
}

while($MoveX -le 0) # 遍历到 MoveX 为 0 。-le :小于等于,如果 MoveX 小于等于0,则进入循环
{
    $MoveX = $MoveX+1
	$x = [Windows.Forms.Cursor]::Position.X-1   # 鼠标当前 X 轴的位置 -1
	$y = [Windows.Forms.Cursor]::Position.Y   # 鼠标当前 Y 轴的位置
	
	$MoveCount = $MoveCount +1
	if ($MoveCount-eq 10)  # 如果移动的次数等于10,则随机变动一下位置,可以去掉,感觉也不太好用。
        {
			$RandomX = Get-Random -Minimum -1 -Maximum 1  # 随机数,最小为-1,最大为1
			$RandomY = Get-Random -Minimum -1 -Maximum 1  # 随机数,最小为-1,最大为1
            $x = $x + $RandomX
			$y = $y + $RandomY
			$MoveCount = 0  # 移动的次数归零
         }
	
	[Windows.Forms.Cursor]::Position = new-object Drawing.Point $x,$y
	Start-Sleep m $speed
}

移动鼠标到指定位置

使用控件:Invoke Power Shell

勾选:IsScript

Paramenters:x3、y3、speed

参数说明:speed 为移动的速度,实际为 Sleep 的毫秒数。

使用说明:这里其实是三阶贝塞尔曲线,当前鼠标位置为起点,而(x1,y1)、(x2,y2) 为控制点,(x3,y3) 为终点。

实际效果:在当前位置上,鼠标开始移动到指定位置

代码思路借鉴了https://www.techotopia.com/index.php/Drawing_Graphics_using_PowerShell_1.0_and_GDI%2B,只不过别人是画图,我是移动鼠标。没有办法,暂时没找到更拟人的轨迹。

可以考虑学习:https://zhuanlan.zhihu.com/p/58284406

# 
Param(
[Parameter(Mandatory=$true)] [Int32]$x3,
[Parameter(Mandatory=$true)] [Int32]$y3,
[Parameter(Mandatory=$true)] [Int32]$speed # 移动的速度,实际为 Sleep 的毫秒数
)

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$x0 = [Windows.Forms.Cursor]::Position.X   # 鼠标当前 X 轴的位置
$y0 = [Windows.Forms.Cursor]::Position.Y   # 鼠标当前 Y 轴的位置

$x1 = 100   # 
$y1 = 100   # 

$x2 = 800   # 
$y2 = 800   # 

# $x3 = 500   # 目标 X 轴的位置
# $y3 = 500   # 目标 Y 轴的位置

$u = 0   # 
while($u -le 1) 
{
	$u = $u+0.005
	$x = [math]::pow( (1-$u) , 3) * $x0 + 3 * [math]::pow( (1-$u) , 2) * $u * $x1 + 3 * [math]::pow( ($u) , 2) * (1-$u) *$x2 + [math]::pow( ($u) , 3) * $x3
	$y = [math]::pow( (1-$u) , 3) * $y0 + 3 * [math]::pow( (1-$u) , 2) * $u * $y1 + 3 * [math]::pow( ($u) , 2) * (1-$u) *$y2 + [math]::pow( ($u) , 3) * $y3

	[Windows.Forms.Cursor]::Position = new-object Drawing.Point $x,$y
	Start-Sleep m $speed
}
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Mouse{
    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int x, int y);
  }
"@

# 模拟鼠标移动到指定位置
[Mouse]::SetCursorPos(100, 100);
# 加载 System.Windows.Forms 命名空间
Add-Type -AssemblyName System.Windows.Forms

# 将鼠标移动到 (100, 100) 的位置
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(100, 100)

浏览器相关

谷歌浏览器,下载前询问每个文件的保存位置

您的连接不是私密连接

solution1:

  • 在当前页面点击一下,然后用键盘输入 thisisunsafe ,不是在地址栏输入,是直接敲键盘。
  • 因为Chrome不信任这些自签名ssl证书,为了安全起见,直接禁止访问。thisisunsafe 这个命令,说明你已经了解并确认这是个不安全的网站,你仍要访问就给你访问了。

solution2

  • 打开chrome://flags
  • 找到“Show in-form warnings for sensitive fields when the top-level page is not HTTPS”设置为 disabled
  • 找到 “Allow invalid certificates for resources loaded from localhost”设置为 “enabled”
  • 点启用,然后重启浏览器

solution3

设置 chrome忽略证书错误

使用 –ignore-certificate-errors 参数命令行打开谷歌浏览器

谷歌浏览器黑屏

原因:可能是因为软件和显卡不兼容

解决办法:禁用硬件加速

打开谷歌浏览器加上参数 –disable-gpu –disable-software-rasterizer

"--test-type --ignore-certificate-errors --no-sandbox --new-window --disable-gpu --disable-gpu-rasterization --disable-gpu-vsync --disable-accelerated-2d-canvas --disable-software-rasterizer "+ in_strSystemUrl

谷歌浏览器崩溃:“STATUS_INVALID_IMAGE_HASH”

https://blog.csdn.net/willingtolove/article/details/106589985

弹出式窗口和重定向

弹出式窗口和重定向1

弹出式窗口和重定向2

弹出式窗口和重定向3

关闭谷歌浏览器异常恢复弹窗

  1. 关闭谷歌浏览器,避免影响;
  2. 打开文件夹;
%UserProfile%\AppData\Local\Google\Chrome\User Data\Default
%LocalAppData%\Google\Chrome\User Data\Default
  1. 找到并打开 Preference 文件;
  2. 修改 Preference 文件中的 exit_type 的值为 Normal;
  3. 修改 Preferrence 文件的属性为只读;

https://docs-repo.uibot.com.cn/application-automation/close-chrome-exception-recovery-popup

https://blog.csdn.net/sarida/article/details/88212125

Win11使用 IE

用 vbs 启动 IE,新建一个记事本,填入下面的内容,重命名记事本为 打开IE.vbs

'打开IE.vbs

CreateObject("InternetExplorer.Application").Visible=true
'IE打开指定网址.vbs

StartURL = "https://www.baidu.com/" 
set IE = CreateObject("InternetExplorer.Application") 
IE.Visible = true 
IE.Navigate StartURL

还有一种方式是 edge,可以使用 IE 模式加载网页

edge://settings/defaultBrowser
edge://compat/sitelistmanager

还有一个办法是替换 ieframe.dll

https://zhuanlan.zhihu.com/p/474585422

如何将文件所有者改为TrustedInstaller:NT SERVICE\TrustedInstaller

修复丢失或损坏的系统文件,用于恢复 ieframe.dll 等文件

以管理员身份,打开cmd ,输入 DISM.exe /Online /Cleanup-image /Restorehealth 回车运行 以管理员身份,打开cmd ,输入 sfc /scannow 回车运行

Win Server 关闭 IE 增强的安全配置

如果设置兼容性视图、加入到信任站点,用 IE 访问网站还是有问题,那么可以试试。

打开服务器管理器,在本机服务器那里找到【IE 增强的安全配置】,把它关闭掉。

iFrame

如果流程用到的系统用了 iFrame,可以试试用新版本的 UiExplorer 能不能识别到,如果可以的话,考虑升级 Studio 版本;如果不行,试一下把浏览器切换成 IE。

奇奇怪怪的坑

ctrl v 失效

ctrl c + ctrl v,无法把复制的内容粘贴到 Excel 文件里面,只输入了一个 v.

原因:未知

解决办法:Send Hotkey 控件勾选 SendWindowMessage.


Selector 能找到元素,但是运行报错 time out

开发时,使用控件的Selector 是能够定位到元素的,但是实际运行的时候,却报错,显示 time out。

原因:网站的问题,网页其实还在加载中,一直都在加载,会加载很久,但是不影响正常使用。(比如说要抓取网页数据,但是有个 gif 文件,一直都加载失败)

解决办法:WaitForReady 属性选择 None


客户机的系统和服务器日期不为同一天

使用到人民币银行结算账户管理系统,登录的时候提示【客户机的系统和服务器日期不为同一天】。

原因:未知

解决办法:用IE浏览器,把网站添加到兼容性视图。

选择元素,F2倒计时结束后元素消失

F2之后,直接鼠标按住元素,倒计时结束后能看到元素,选择元素。

Cannot find the UI element corresponding to this selector

背景信息:确认有元素,且不会变动,selector 验证是通过的,但是运行的时候报错。

异常情况:selector 不止一个 /selector 不对

解决办法1:图像识别

解决办法2:不要用 attach window

解决办法3:把界面最小化之后,再去点击。

Cannot communicate with the browser, please check the UiPath extension

背景信息:uipath扩展程序没有问题

异常情况:报错说连接不到浏览器,检查一下uipath扩展程序

解决办法:看看输入的浏览器的地址是否为空,为空则跳过

你要允许来自未知发布者的此应用对你的设备进行更改吗?

Solution1:

点击显示详细信息,选择何时显示更改通知,改为【从不通知】

不太推荐

Solution2:

  • Win + R,输入 regedit,然后回车。
  • 在注册表编辑器内,找到HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
  • 提前把 .exe 文件的路径复制

  • 在空白处右键,选择新建,字符串值,把复制的路径填入

  • 在数值数据处,输入 RunAsInvoker

  • 点击确定,完成

Solution3:

如果是远程机器使用 UiPath RemoteRuntime 的话,可以考虑去找到UiPath RemoteRuntime.exe 的路径,右键,在属性里面的兼容性里,勾选以管理员身份运行此程序

以管理员身份运行Uipath应用程序

识别元素报错:无法访问目标流程!可能需要提升权限,尝试以管理员身份运行Uipath应用程序。

如果是识别本机元素,那就找到 UiPath.Studio.exe 、UiPath.Executor.exe、UiRobot.exe ,勾选以管理员身份运行此程序。

如果是识别远程机器的元素,那就在远程的机器里面,找到 UiPath RemoteRuntime.exe ,勾选以管理员身份运行此程序。

勾选以管理员身份运行此程序的方式:找到指定 exe 文件,右键,点击属性,在兼容性里面,勾选【以管理员身份运行此程序】

勾选以管理员身份运行此程序

Block User Input 锁不了鼠标键盘

用 ToDesk 连接到别的机器的话,确实不行…

以管理员身份运行UiPath.Executor.exe,没用;

以管理员身份运行UiPath Studio,再执行流程,直接报错

RemoteException wrapping System.AggregateException: One or more errors occurred. (拒绝访问。)  ---> RemoteException wrapping System.ComponentModel.Win32Exception: 拒绝访问。 
   at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)
   at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
   at System.Diagnostics.Process.GetOrOpenProcessHandle()
   at System.Diagnostics.Process.EnsureWatchingForExit()
   at System.Diagnostics.Process.set_EnableRaisingEvents(Boolean value)
   at UiPath.Service.UserHost.AttendedServiceProxy.RegisterClientProcess(Int32 clientPid)
   at UiPath.Service.UserHost.StudioOperations.Prepare(ClientProcessMessage message, CancellationToken ct)
   at UiPath.Service.Core.Utils.TaskUtils.WithShortWait(Task task, TimeSpan wait)
   at UiPath.Service.UserHost.StudioOperations.<>c__DisplayClass7_0.<<RunJob>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.CancellationHelper`1.Invoke[TResult](TId requestId, Func`2 func)
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_3.<<-ctor>g__InvokeMethod|6>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_1.<<-ctor>g__HandleRequest|3>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_2.<<-ctor>b__5>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Helpers.Timeout[TResult](TimeSpan timeout, List`1 cancellationTokens, Func`2 func, String message, Func`2 exceptionHandler)
	--- End of inner exception stack trace ---
   at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)
   at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
   at System.Diagnostics.Process.GetOrOpenProcessHandle()
   at System.Diagnostics.Process.EnsureWatchingForExit()
   at System.Diagnostics.Process.set_EnableRaisingEvents(Boolean value)
   at UiPath.Service.UserHost.AttendedServiceProxy.RegisterClientProcess(Int32 clientPid)
   at UiPath.Service.UserHost.StudioOperations.Prepare(ClientProcessMessage message, CancellationToken ct)
   at UiPath.Service.Core.Utils.TaskUtils.WithShortWait(Task task, TimeSpan wait)
   at UiPath.Service.UserHost.StudioOperations.<>c__DisplayClass7_0.<<RunJob>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.CancellationHelper`1.Invoke[TResult](TId requestId, Func`2 func)
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_3.<<-ctor>g__InvokeMethod|6>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_1.<<-ctor>g__HandleRequest|3>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_2.<<-ctor>b__5>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Helpers.Timeout[TResult](TimeSpan timeout, List`1 cancellationTokens, Func`2 func, String message, Func`2 exceptionHandler)

批量插入数据(Insert DataTable)到数据库报错

查询没问题,单条插入也没问题,就是批量插入有问题。

报错:

ERROR [42000] [MySQL][ODBC 3.51 Driver][mysqld-8.0.28]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DEFAULT VALUES' at line 1

解决办法:

把 UiPath.Database.Activities 版本改为 1.4.0

UiPath Data Scraping只能抓取网页表格的数据

问题:只能抓取表格的数据,不能单独爬取一列一列的数据。

selector还会有点问题,像 window 软件的 selector

<ctrl role='grouping' text='展开' />

而不像是网页的selector,

<webctrl aaname='展开' tag='SPAN' />

解决办法:重启 Uipath Studio

报错:Scrape returned empty text

ocr识别的时候出图像错,因为图像没加载出来,但是元素存在。

能运行的代码,突然有一天不能运行了1

检查一下最近有没有安装什么软件,导致冲突了。

注:特指福昕阅读器。

检查一下有没有什么软件自动更新,导致出现问题了。

注:特指福昕阅读器。

只是看 PDF 的话,SumatraPDF 其实也可以的,

能运行的代码,突然有一天不能运行了2

检查一下某些安全软件有没有升级,导致文件无法删除。

IsNumeric() 报错

Compiler error(s) encountered processing expression “IsNumeric(CurrentRow(0).ToString)”. 没有类的显式实例,就无法从共享方法或共享成员初始值设定项中引用该类的实例成员。

解决办法:

"7".IsNumeric
Microsoft.VisualBasic.IsNumeric("7")
Microsoft.VisualBasic.Information.IsNumeric("7")

Studio 运行流程报错 Unable to start execution

UiPath Studio 版本,2019.4,在 Studio 运行流程,出现弹窗提示:Could not connect to UiPath Robot Service. Make sure the service is started!

试一下重启 Robot,如果还不行,那就在服务里面找到 UiPath Robot,启动一下 UiPath Robot。

https://forum.uipath.com/t/could-not-connect-to-uipath-robot-service-make-sure-the-service-is-started/99683/4

UiPath 相关

教程

https://docs.uipath.com/studio/lang-zh_CN/docs/tutorials

UiPath 包路径

包含依赖包、发布在本地的包

%UserProfile%\.nuget\packages

UiPath 本地依赖包路径

nupkg 包

社区版:

%UserProfile%\AppData\Local\Programs\UiPath\Studio\Packages
%LocalAppData%\Programs\UiPath\Studio\Packages

企业版:

C:\Program Files (x86)\UiPath\Studio\Packages

UiPath Studio.exe 的路径

社区版:

%UserProfile%\AppData\Local\Programs\UiPath\Studio\UiPath.Studio.exe
%LocalAppData%\Programs\UiPath\Studio\UiPath.Studio.exe

企业版:

C:\Program Files (x86)\UiPath\Studio\UiPath.Studio.exe

UiPath UiRobot.exe 的路径

社区版

%UserProfile%\AppData\Local\Programs\UiPath\Studio\UiRobot.exe
%LocalAppData%\Programs\UiPath\Studio\UiRobot.exe

企业版

C:\Program Files (x86)\UiPath\Studio\UiRobot.exe

UiPath 本地日志的路径

%UserProfile%\AppData\Local\UiPath\Logs
%LocalAppData%\UiPath\Logs

UiPath 术语表(UiPath Glossary)

https://docs.uipath.com/overview-guide/lang-zh_CN/docs/uipath-glossary

产品生命周期(product lifecycle)

https://docs.uipath.com/overview-guide/lang-zh_CN/docs/product-lifecycle

活动生命周期(activities lifecycle)

https://docs.uipath.com/overview-guide/lang-zh_CN/docs/activities-lifecycle

弃用 Windows 旧版兼容性

https://docs.uipath.com/studio/lang-zh_CN/docs/deprecation-of-the-windows-legacy-compatibility

UiPath Studio

输入方法

Default、SendWindowMessages、SimulateType(SimulateClick)

UiPath 输入方法

Default:基于系统驱动的方式,来模拟键盘和鼠标行为。是最接近真实的鼠标和键盘的方式。

SendWindowMessages:通过向应用程序发送Window Message进行模拟的。是基于应用的方式。

SimulateType(SimulateClick):通过向UI元素发送消息进行模拟的。是基于UI元素的。

类型 基于 兼容程度 响应速度
Default 系统驱动(最接近真实鼠标键盘的方式) 全部
SendWindowMessages 应用 大部分
SimulateType(SimulateClick) UI元素 一部分
类型 光标 文字
Default 本来在其他应用程序窗口的光标,会移动到txt文本框内。 文字是一个个打出的
SendWindowMessages 在其他应用程序窗口的光标不会被移动 文字是一个个打出的
SimulateType 在其他应用程序窗口的光标不会被移动 文字是瞬间出来的

https://docs.uipath.com/studio/lang-zh_CN/docs/ui-automation#section-input-methods

https://www.cnblogs.com/toseeme/p/13497944.html

UiPath Robot

如果机器人已连接到 Orchestrator ,则所有执行日志都将发送到 Orchestrator,并可以在“日志”页面中看到。

如果 Orchestrator 处于不可用状态,则在连接恢复前,系统会将日志存储在可用磁盘空间的本地数据库 (C:\Windows\SysWOW64\config\systemprofile\AppData\Local\UiPath\Logs\execution_log_data) 中。恢复连接后,系统会按日志的生成顺序将其分批发送。

在某些特定情况下文件可能会损坏、日志无法上传成功、无法打印日志。解决方法是将此文件夹下的文件删除,计算机、UiRobot服务重启。