EXCEL VBA 檔案輸入 LINE INPUT
首先有一個檔案text1.txt內容如下,! 後面接的是註解內容不處理,後面的檔案格式是用Comma "," 隔開,也就是縮為的CSV Comma Separated Value檔案格式。
! MacGyFu Python Learning Notes
! data format [d1],[d2],[d3],[d4]
ff,12,10,20
33,11,44,55
66,77,88,99
ac,f1,78,8c
如果用Notepad開啟可以看到的內容如下。
Excel 我們先拉一個Button,然後程式碼如下,只要用到 VB code的檔案開啟Open()與Line Input ()這兩個函數,每一行讀入的時候利用VB內建的字串函數Mid()判斷每一行的字元是不是"!",如果不是在進行處理把每一行的用Comma隔開的資料傳到sorting()傳回一維陣列,然後把資料貼到Excel上面。
Private Sub CommandButton1_Click()
Dim file As String
Dim in_str As String
Dim i, j As Integer
file = "text1.txt"
Dim data() As String
Open ThisWorkbook.Path & "\" & file For Input As #1
i = 0
j = 0
Do While Not EOF(1)
Line Input #1, in_str 'Line Input
If Mid(in_str, 1, 1) = "!" Then
'Do Nothing
Else
Call sorting(data, in_str, ",")
For i = 0 To UBound(data)
Cells(6 + j, 1 + i) = data(i)
Next i
j = j + 1
End If
Loop
Close #1
End Sub
以下是sorting函數的寫法,當然這些都是一些字串的處理,每個人寫出來的會不太一樣,
Public Sub sorting(ByRef value() As String, ByVal in_str As String, Optional mark As String = " ")
Dim i As Integer
Dim j As Integer
Dim temp As String
temp = in_str
i = 1
j = 0
ReDim value(j)
For i = 1 To Len(temp)
If Mid(temp, i, 1) = mark Then
j = j + 1
i = i + 1
ReDim Preserve value(j)
End If
value(j) = value(j) & Mid(temp, i, 1)
Next i
For i = 0 To UBound(value)
value(i) = Trim(value(i))
Next i
End Sub
讓我們看一下執行的結果
EXCEL VBA LF and CRLF換行字元處理
但很多時候會遇到以下的問題,大部的工廠測試機台的系統是跑在UNIX系統,UNIX系統的換行字元為LF (\n),但Windows系統則是CRLF (\r\n),所以會遇到用微軟系列的文字處理函數會遇到他認為這個檔案只有"一行"。
所以這裡處理就要修改一下,Line Input改成Input()逐字讀入,直到讀到LF (Chr(10))就換行丟入sorting()處理,所以整個程式流程等於是自己寫了Line Input()這個Function。
Line Input() 逐行行入
Input() 逐字讀入
Private Sub CommandButton1_Click()
Dim file As String
Dim in_str As String
Dim i, j As Integer
Dim temp As String
file = "text1_LF.txt"
Dim data() As String
Open ThisWorkbook.Path & "\" & file For Input As #1
i = 0
j = 0
Do While Not EOF(1)
'Line Input #1, in_str 'Line Input
temp = ""
in_str = ""
Do Until temp = Chr(10) Or EOF(1)
temp = Input(1, #1)
in_str = in_str & temp
Loop
in_str = Replace(in_str, Chr(10), "")
If Mid(in_str, 1, 1) = "!" Then
'Do Nothing
Else
Call sorting(data, in_str, ",")
For i = 0 To UBound(data)
Cells(6 + j, 1 + i) = data(i)
Next i
j = j + 1
End If
Loop
Close #1
End Sub
Python 怎麼寫?
Python研究了幾天,在檔案處理部分其實差不多,但針對CSV已經有現成的函數可以使用,只要import csv就可以開始呼叫使用,但新手就練習一下如果自己寫會長的怎樣,主程式內容如下,基本上跟VBA的流程一樣,呼叫語法有點不一樣而已。
#Open File
try:
with open("text1.txt","r",encoding="utf-8") as f:
#case 1 read all
count=0
column=2
for result in f:
temp = result.replace("\n","")
if temp == "":
pass
elif temp[0] == "!":
pass
else:
row=sorting(temp,",")
print (count," ",row)
print ("index 0 >",row[0])
count+=1
except IOError as err:
print ("檔案開啟錯誤 Err=",err)
finally:
print("結束")
其中的sorting寫法如下
def sorting(instr,delimiter =","):
matrix=[]
i=0
j=0
temp=""
while (i<len(instr)):
if instr[i] != delimiter:
temp=temp+instr[i]
i+=1
elif instr[i] == delimiter:
matrix.append(temp)
j+=1
i+=1
temp=""
if i > (len(instr)-1):
matrix.append(temp)
break
return matrix
最後執行的結果如下,可以把每一行的資料分開,後續就可以針對每個資料進行運算處理。
Python內建CSV函數
其實針對csv檔案,Python也有提供現成的csv處理,只要import csv後就可以使用,所以就少寫sorting()這個函數,跑出來的結果也一樣,另外Python的檔案處理則不用特別處理這個問題LF與CRLF這兩種差別。
import csv
#Open File
try:
with open("text1.txt","r",encoding="utf-8") as f:
#case 1 read all
count=0
column=3
rows = csv.reader(f, delimiter=',')
for row in rows:
if row[0][0] != "!":
count+=1
print(row)
print ("index 0 >",row[0])
except IOError as err:
print ("檔案開啟錯誤 Err=",err)
finally:
print("結束")
Touchstone S Parameter
如果有現成的可以用當然直接用,但沒有的時候還是要自己處理了,例如RF工程師會常遇到S parameter (Touch Stone)可以參考Keysight Save Trace Data in Touchstone Format的文件,這類型的文件檔案之間比較類似文字對齊的方式,讓人可以直接閱讀方便,所以每行間的資料並不是用Comma ","或固定空格" ",每一筆資料可能有不同的空格或插入TAB讓資料排列整齊。
我們用上述處理csv的方式 (python用的是內建csv函數),分隔符號delimiter用空格符號" ",跑出來的結果如下,因為空格符號可能會連續2-3個,所以會誤認有些資料是"空格"。
EXCEL VBA 處理Touch Stone Like
所以在這樣的Case我們可以假設連續出現的Delimiter 為相同的分隔訊號,直到下次非分隔訊號為止,我們可以改寫sorting的程式碼如下。
Public Sub sorting(ByRef value() As String, ByVal in_str As String, Optional mark As String = " ")
Dim i As Integer
Dim j As Integer
Dim temp As String
Dim Duplicate_Mark_Remove As Boolean
Duplicate_Mark_Remove = False
temp = in_str
i = 1
j = 0
ReDim value(j)
For i = 1 To Len(temp)
If Mid(temp, i, 1) <> mark And (Duplicate_Mark_Remove = False) Then
value(j) = value(j) & Mid(temp, i, 1)
ElseIf Mid(temp, i, 1) = mark And (Duplicate_Mark_Remove = False) Then
Duplicate_Mark_Remove = True
ElseIf Mid(temp, i, 1) = mark And (Duplicate_Mark_Remove = True) Then
Duplicate_Mark_Remove = True
ElseIf Mid(temp, i, 1) <> mark And (Duplicate_Mark_Remove = True) Then
Duplicate_Mark_Remove = False
j = j + 1
ReDim Preserve value(j)
value(j) = value(j) & Mid(temp, i, 1)
End If
Next i
For i = 0 To UBound(value)
value(i) = Trim(value(i))
Next i
End Sub
Python 處理Touch Stone Like
其實是EXCEL VBA Code把一樣的動作邏輯改成Python的語法,
def sorting(instr,delimiter =","):
matrix=[]
i=0
j=0
temp=""
Duplicate_Delimiter_Flag = False
while (i<len(instr)):
if (instr[i] != delimiter and (Duplicate_Delimiter_Flag == False)):
temp=temp+instr[i]
i+=1
elif (instr[i] == delimiter and (Duplicate_Delimiter_Flag == False)):
Duplicate_Delimiter_Flag =True
i+=1
elif (instr[i] == delimiter and (Duplicate_Delimiter_Flag == True)):
Duplicate_Delimiter_Flag = True
i=i+1
elif (instr[i] != delimiter and (Duplicate_Delimiter_Flag == True)):
Duplicate_Delimiter_Flag = False
matrix.append(temp)
j+=1
temp=""
temp=temp+instr[i]
i+=1
if i > (len(instr)-1):
matrix.append(temp)
break
return matrix
執行結果就可以得到預期的效果了
這次練習的EXCEL VBA與Python py檔我就放在Google雲端硬碟有需要的在自己下載參考。
.
.
......
沒有留言:
張貼留言