你好,
我正在开发一个加载项,以水平连接来自 OSIsoft-PI 连接器的值,因为它在单独的表上打开每个标签,其中列 (1) 是时间戳,列 (2) 是标签的值。我找到了一种解决方法“更新”哪个工作正常. 但是我最初的计划是使用“加入”避免在时间戳未对齐时收集行,并避免像“更新”策略一样删除行的最后一步。不幸的是,我遇到了各种错误消息,并希望更好地理解如何使加入工作(用于进一步的脚本工作)。 查找附加的 Word 文档,其中包含有关步骤和错误的更多详细信息,以及脚本(更新有效,而加入失败)和数据表。
感谢您的帮助,我愿意参加团队会议或文档。
伊曼纽尔
嗨 Emmanuel,您可以试试这个,它循环连接过程并且只有最少的表达式处理。
Names Default To Here( 1 );
// List of opened files
file = Get Data Table List();
n_files = N Items( file );
joinCol = "Timestamp";
joinedDt = file[1];
For Each( {i}, 2 :: (n_files), // i =2;
Eval(
Eval Expr(
joinedDt = joinedDt << Join(
With( file[i] ),
By Matching Columns( Expr( Parse( Eval Insert( ":^joinCol^" ) ) ) = Expr( Parse( Eval Insert( ":^joinCol^" ) ) ) ),
Drop multiples( 0, 0 ),
Include Nonmatches( 0, 0 ),
Preserve main table order( 1 ),
invisible
)
)
);
//set first column to join column name
Column( joinedDt, 1 ) << set name( joinCol );
//delete working files and prepare for next time through loop
Close( file[i], nosave );
Try( Close( oldJoin, nosave ) );
oldJoin = joinedDt;
);
Close( file[1], nosave );
//remove extra join columns
For Each( {i}, N Col( joinedDt ) :: 2,
If( Lowercase( Left( Column( joinedDt, i ) << get name, 9 ) ) == Lowercase( joincol ),
joinedDt << delete columns( i )
)
);
joinedDt << show window( 1 );
谢谢布雷迪,有用.
现在我要睡觉了,明天(或星期一)我会尝试理解确切地这个怎么运作
。
谢谢你。
如果您在查看后有任何问题,请告诉我,我很乐意详细说明/致电。
干杯,
布雷迪
修理Script_Concatenate_Tags_w_JOIN_Fail_2 :
将第 70 行更改为: Expr (dt_joined = dt_joined << Join(
删除第 80 行: Expr (dt_joined), 当前数据表 () ,
在我看来,当前数据表()应该只用于在脚本开始时获取当前表,因为这是您确定它所引用的表(用户最后触摸的表)的少数几次之一。 在许多其他情况下,当前表可能因运行而异,具体取决于正在执行的操作、它们花费的时间、用户在处理事情时是否触摸了另一个表、底层代码的更改是否导致了当前表一个版本中的表格以在下一个版本中更改,等等。 你使用的方式当前数据表()这就是您的脚本“有效”的原因(它将文件中的第二个表与您选择的表连接起来)。 我坚信应该只明确引用表。 这就是在新的第 70 行中所做的事情,您可以肯定地知道它既是正在发送消息的表,也是传递结果表的变量。
使用表达式将列名输入平台是很棘手的,特别是当参数可以采用多个列时。 在找到有效的方法之前,我几乎总是需要尝试一些不同的方法。 我相当肯定这个功能多年来一直在发展,幸运的是变得更好(更灵活)。 尽管如此,这仍然是一个挑战。 @Mark_Bailey有一篇关于使用专栏的精彩文章我建议阅读。
在里面Script_Concatenate_Tags_w_JOIN_Fail_1脚本,第一个加入块,问题不在于解析,但尝试将对该列的引用插入到列表中(JMP 找不到该列)。 虽然你可以有多个语句代替(我经常这样做),在这种情况下你不需要。 可以直接放入加入使用它的名称而不是它的号码(我无法上班)。 最重要的是,您可以从连接的表中获取所有列,以及从表中获取除第一列之外的所有列来加入它。 我重新排列了代码,以便可以显式引用表和列并删除我不需要的表。
name = Get Data Table List(); <BR />For(i=1,i<=N Items(name),i++, name[i] = Head Name(name[i]));<BR /><BR />join1 = Data Table(1);
for (f=2, f<= N Items(name),f++,
colList1 = join1 << Get Column Names();
colList2 = Remove(Data Table(name[f]) << Get Column Names(),1);
Eval(
Substitute(
Expr (
dt_joined = join1 << Join(
With( join2 ),
Select(cl1),
SelectWith( cl2 ),
By Matching Columns( join1Col1 = join2Col1),
Drop multiples( 0, 0 ),
Include Nonmatches( 0, 0 ),
Preserve main table order( 1 )
)
) ,
Expr (join2), Data Table(name[f]),
Expr(cl1), Name Expr(colList1),
Expr(cl2), Name Expr(colList2),
Expr (join1Col1), Column(join1,1),
Expr (join2Col1), Column(Data Table(name[f]),1),
)
);
Close(join1,No Save);
Close(Data Table(name[f]),No Save);
join1 = dt_joined;
);
我已经在代码的顶部整理了一些东西,你不需要创建一个表来收集表名。 将名称放入列表并从中工作要简单得多。 如果桌子很大,这可能有点笨拙。 最好用无形的或者私人的隐藏中间表。 问题是,据我所知,没有办法使用消息取消隐藏决赛桌。 您可以使用整个表格制作一个子集来重新显示它。
你好唐,谢谢!
*为了Script_Concatenate_Tags_w_JOIN_Fail_2,正如你所说,我用过当前数据表()使它起作用,但我怀疑这不是最好的方法。 现在我知道解决方案与 dt_joined = dt_joined << Join() 非常接近,但我自己永远不会想到它(现在我明白了“表消息和结果表传递到的变量“我希望将来会考虑它)。
*对于 Script_Concatenate_Tags_w_JOIN_Fail_1,使用正确的命令确实要简单得多(例如 name[i] = Head Name(name[i] or colList2 = Remove(Data Table(name[f]) << Get Column Names(),1 )
而不是构建复杂的东西来实现它(很高兴知道)。
再次感谢你。