VB.NET/UiPath下使用LINQ提取DataTable每行最右非0列的实现
UiPath DataTable 格式化处理实现方案
核心逻辑
该需求可直接通过VB.NET LINQ实现,适配UiPath原生运行环境,无需额外依赖。处理逻辑为:保留原表ID、Name前两列,逐行从右往左查找第一个数值不为0的周列,取该值作为Value列,最终输出仅含三列的目标DataTable。
LINQ 实现代码(推荐)
直接在UiPath的Invoke Code活动中运行即可,注意替换sourceDt为你自己的原始DataTable变量名:
' 1. 构造目标表结构,列类型可匹配原表对应字段调整 Dim targetDt As New DataTable() targetDt.Columns.Add("ID", GetType(String)) targetDt.Columns.Add("Name", GetType(String)) targetDt.Columns.Add("Value", GetType(Decimal)) ' 2. LINQ 批量处理所有行 targetDt = (From row In sourceDt.AsEnumerable() ' 跳过前两列基础字段,取所有周数据列 Let weekColumns = sourceDt.Columns.Cast(Of DataColumn)().Skip(2) ' 周列按位置倒序排列,查找第一个非0值,自动处理空值为0 Let latestNonZeroValue = weekColumns.OrderByDescending(Function(col) col.Ordinal) _ .Select(Function(col) If(IsDBNull(row(col)), 0, Convert.ToDecimal(row(col)))) _ .FirstOrDefault(Function(val) val <> 0) ' 拼接新行写入目标表 Select targetDt.LoadDataRow({row("ID"), row("Name"), latestNonZeroValue}, False)).CopyToDataTable()
常规循环写法(适合新手调试)
如果对LINQ不熟悉,可使用常规循环写法,逻辑完全一致:
Dim targetDt As New DataTable() targetDt.Columns.Add("ID", GetType(String)) targetDt.Columns.Add("Name", GetType(String)) targetDt.Columns.Add("Value", GetType(Decimal)) For Each row As DataRow In sourceDt.Rows Dim value As Decimal = 0 ' 从最后一列倒序遍历到第三列(列索引从0开始,前两列是0、1) For i As Integer = sourceDt.Columns.Count - 1 To 2 Step -1 Dim cellVal = If(IsDBNull(row(i)), 0, Convert.ToDecimal(row(i))) If cellVal <> 0 Then value = cellVal Exit For End If Next targetDt.Rows.Add(row("ID"), row("Name"), value) Next
边缘情况说明
若某一行所有周列均为0或空值,最终Value列默认返回0,如需修改默认值可调整
latestNonZeroValue或循环中value的初始值即可。
使用注意事项
- 两种写法都可直接放入
Invoke Code活动,需要将sourceDt设置为导入变量,targetDt设置为导出变量 - 如果原始表ID、Name列是数值类型,将构造列时的
GetType(String)替换为对应类型即可
内容的提问来源于stack exchange,提问作者Conor
相关产品推荐
相关产品推荐

