2014-07-23 2 views
0

때로는 먼저 치수를 지정하지 않고 배열을 채우는 문제에 직면합니다. 대부분의 경우 루프를 통해 조건이 몇 번 확인되었는지 확인할 수 있습니다. 따라서 ReDim 내 배열이 적절하고 루프와 동일한 매우 동일한 루프 배열로 데이터를 채 웁니다.
이것은 (특히 거대한 배열과 함께) 매우 시간이 많이 걸리고 최적화되지 않았습니다.VBA - 치수 지정하지 않고 배열에 데이터 삽입

오늘 텍스트 파일을 프로그래밍 방식으로 "읽는 중"이라는 것을 발견했습니다. 텍스트 파일을 읽는 횟수가 얼마나되는지에 대한 실마리가없는 빈 줄 이전에 줄이 몇 번 반복되었는지를 확인해야했습니다. 나는 "그것을 읽고"다음 코드를 사용

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 

: 나는 그런 라인의 최소 수는 파일은 다음과 같습니다 1.

만 알고

Dim i As Integer 
Dim fd As FileDialog, FilePath As String 
Dim fst As Object, StringData As String 
Dim Name As String, Frequency As Double, DefDiag() As String 

Set fd = Application.FileDialog(msoFileDialogFilePicker) 
With fd 
    .Title = "Select the file you would like to import" 
    .AllowMultiSelect = False 
    .Filters.Clear 
    .Filters.Add "Potato File", "*.pot" 
    .FilterIndex = 1 
    If .Show <> -1 Then 
     End 
    End If 
    FilePath = .SelectedItems(1) 
End With 

Set fst = CreateObject("ADODB.Stream") 
fst.Charset = "utf-8" 
fst.lineseparator = 10  ' sets enter as end-of-line separator 
fst.Open 
fst.LoadFromFile FilePath 

StringData = fst.ReadText(-2) ' -2 to read until lineseparator 
Name = Mid(StringData, 7) 
StringData = fst.ReadText(-2) 
StringData = fst.ReadText(-2) 
Frequency = CDbl(Mid(StringData, 11)) 
Do Until fst.ReadText(-2) = "" 
    StringData = fst.ReadText(-2) ' DEF_DIAG 
    DefDiag(i) = Right(StringData, Len(StringData) - InStrRev(StringData, " ")) 
    i = i + 1 
Loop 

당연히 그것을 DefDiag 어레이가 채워지기 시작하는 위치에서 멈 춥니 다. 치수를 지정하지 않는 방법에 대한 아이디어가 있습니까?

답변

1

나는 그것이 VBA에서 차원 않고 배열을 채울 수 있다고 생각하지 않지만, 반복하는 동안 배열을 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 
+0

멋지고 매끄러운 트릭! 내가 필요한 것 – Noldor130884

1

;

  • 로드 라인

    Open FilePath For Input As #1 DefDiag = Split(Input$(LOF(1), #1), ChrW$(10)) Close #1

  • 배열로 파싱 메모리에 전체 파일, 제 2 어레이에게 프로세싱 일 DefDiag

  • 루프 DefDiag 같은 크기를 할당 값을 저장할 때 두 번째 배열의 다음 인덱스에 추가

  • 때 당신의 빈 꼬리를 잘라내는 Redim 2 차 배열을 수행

+0

+1 도움을 받으려면 'Open FilePath For Input As # 1'또는 2 개의 어레이를 사용해야한다는 사실을 좋아하지 않습니다. 이렇게하면 "이중 루프"문제를 해결할 수 없습니다. – Noldor130884

+0

효율성에 대해 걱정한다고 가정 했으므로 IMO를 줄마다 할당하지 않고 총 1 개의 루프 및 3 개의 배열 할당으로 간주하기가 어렵습니다. 또한 외부 종속성에 대한 후기 바인딩 COM 호출도 없습니다. –

+0

글쎄, 배열에 전체 파일을로드해야합니다 ...이 일종의 루프 아닌가요? 반복되는 일련의 줄이 있다면 여러 번 반복해야한다고 생각합니다 (특히 처리 할 때 - 순차적으로 다른 데이터를 만듭니다). 또한 루프 반복 횟수가 적을 때처럼 효율적인지 알 수 없습니다. Loop + Redim Preserve는 시간이 오래 걸릴 것입니다. – Noldor130884

관련 문제