Arrays VBA-在数组中插入数据而不标注其尺寸
有时我发现自己面临着填充数组而不必首先对其进行尺寸标注的问题。大多数情况下,我可以通过一个循环来验证一个条件被验证了多少次,Arrays VBA-在数组中插入数据而不标注其尺寸,arrays,vba,text,dimensions,Arrays,Vba,Text,Dimensions,有时我发现自己面临着填充数组而不必首先对其进行尺寸标注的问题。大多数情况下,我可以通过一个循环来验证一个条件被验证了多少次,ReDimmy array相应地,然后通过同一个循环将数据填充到数组中。这(特别是对于庞大的数组)非常耗时且未优化 今天,我发现自己以编程方式“读取”一个文本文件,在这个文件中,我必须验证一行在一个空行之前重复了多少次,而不知道可能有多少次。我只知道这类线路的最小数量是1条 该文件如下所示: TITLE Very_Much_Potato INFO lol? FREQUENC
ReDim
my array相应地,然后通过同一个循环将数据填充到数组中。这(特别是对于庞大的数组)非常耗时且未优化 今天,我发现自己以编程方式“读取”一个文本文件,在这个文件中,我必须验证一行在一个空行之前重复了多少次,而不知道可能有多少次。我只知道这类线路的最小数量是1条 该文件如下所示:
TITLE Very_Much_Potato
INFO lol?
FREQUENCY 123456.7
DEF_DIAG 1 Potato1.TXT
DEF_DIAG 2 Potato2.TXT
ELEMENT 1 0.00 0.00 -300.00 0.250 0.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 2 0.00 0.00 -200.00 0.500 20.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 3 0.00 0.00 -100.00 0.750 40.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 4 0.00 0.00 0.00 1.000 60.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 5 0.00 0.00 100.00 0.750 80.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 6 0.00 0.00 200.00 0.500 100.0 6.0 1 2 0.00 0.0 0.0
ELEMENT 7 0.00 0.00 300.00 0.250 120.0 6.0 1 2 0.00 0.0 0.0
END
我使用以下代码“阅读它”:
Dim i作为整数
Dim fd作为文件对话框,文件路径作为字符串
Dim fst作为对象,StringData作为字符串
Dim名称为字符串,频率为双精度,DefDiag()为字符串
Set fd=Application.FileDialog(msoFileDialogFilePicker)
有fd
.Title=“选择要导入的文件”
.AllowMultiSelect=False
.过滤器
.Filters.Add“马铃薯文件”、“*.pot”
.FilterIndex=1
如果.Show-1那么
终点
如果结束
文件路径=.SelectedItems(1)
以
设置fst=CreateObject(“ADODB.Stream”)
fst.Charset=“utf-8”
fst.lineseparator=10'集作为行尾分隔符输入
开放
fst.LoadFromFile文件路径
StringData=fst.ReadText(-2)'-2读取,直到行分隔符
名称=中间(StringData,7)
StringData=fst.ReadText(-2)
StringData=fst.ReadText(-2)
频率=CDbl(中间(StringData,11))
直到fst.ReadText(-2)=
StringData=fst.ReadText(-2)'DEF_DIAG
DefDiag(i)=右(StringData,Len(StringData)-InStrRev(StringData,“”))
i=i+1
环
当DefDiag
数组开始填充时,它自然停止。有没有关于如何不标注尺寸的想法?我会的
- 将整个文件加载到内存中,并解析为行数组
将输入文件路径打开为#1 DefDiag=Split(输入$(LOF(1),#1),ChrW$(10)) 关闭#1
- 分配第二个数组,其大小与
DefDiag
- 循环
进行处理,在需要存储值时添加到第二个数组的下一个索引DefDiag
- 当您完成
时,第二个数组将截断其空尾部Redim
ReDim-Preserve
在循环时重拨数组:
...
i=1
Do Until fst.ReadText(-2) = ""
StringData = fst.ReadText(-2) ' DEF_DIAG
ReDim Preserve DefDiag(i)
DefDiag(i) = Right(StringData, Len(StringData) - InStrRev(StringData, " "))
i = i + 1
Loop
+1提供帮助,但我既不喜欢输入为#1的
打开文件路径,也不喜欢需要使用2个数组。这样做并不能解决“双循环”问题。我假设您担心效率,这是很难克服的,因为IMO总共分配了1个循环&3个数组,而不是每行分配。也没有对外部依赖项的后期绑定COM调用。您必须在数组中加载整个文件。。。这不是一种循环吗?然后,如果我有更多的重复行序列,我想我应该循环同样多的次数(特别是在我的处理过程中——它按顺序构建其他数据)。另外,我也不知道它的效率是否和少数重复行一样:Loop+Redim-Preserve应该花费更少的时间。Aye-Split将使用一个循环,但是一个在VB运行时内用C/++实现的循环将非常快速和高效。如果不对某个特定案例进行基准测试,这是不可能的,但是对于大型阵列来说,Redim preserve
通常被认为是一项非常昂贵的操作,因为它必须占用整个现有阵列,重新分配、复制和返回。我不知道您是否懂德语,但是有一个家伙,他对一个数组进行了5000次ReDim
edPreserve
d操作,并声称性能还不错。他说,ReDim-Preserve
是在旧的VB.NET中构建的,因此它应该非常高效。你有更多关于它“昂贵”的信息吗?
...
i=1
Do Until fst.ReadText(-2) = ""
StringData = fst.ReadText(-2) ' DEF_DIAG
ReDim Preserve DefDiag(i)
DefDiag(i) = Right(StringData, Len(StringData) - InStrRev(StringData, " "))
i = i + 1
Loop