[ Main Page ]

VBA (Visual Basic for Applications) ファイル操作

Praatという音声分析ソフトのレポート出力をExcelにまとめたいという要望があり、VBAで作成したので、 ファイル操作やダイアログで複数選ぶ時や文字列を抽出する方法を参考までに。Pulses/Voice Reportの出力は以下の様になっており、 複数のファイルのそれぞれの項目を表にする。ReadFiles()を実行。

	-- Voice report for 1. Sound a_1 --
	Date: Wed Feb 28 14:37:38 2018

	WARNING: some of the following measurements may be imprecise.
	For more precision, go to "Pitch settings" and choose "Optimize for voice analysis".

	Time range of SELECTION
	   From 0.040134 to 0.176291 seconds (duration: 0.136157 seconds)
	Pitch:
	   Median pitch: 117.024 Hz
	   Mean pitch: 118.316 Hz
	   Standard deviation: 3.136 Hz
	   Minimum pitch: 114.442 Hz
	   Maximum pitch: 126.613 Hz
	Pulses:
	   Number of pulses: 16
	   Number of periods: 15
	   Mean period: 8.485830E-3 seconds
	   Standard deviation of period: 0.200097E-3 seconds
	Voicing:
	   Fraction of locally unvoiced frames: 7.143%   (1 / 14)
	   Number of voice breaks: 0
	   Degree of voice breaks: 0   (0 seconds / 0 seconds)
	Jitter:
	   Jitter (local): 1.051%
	   Jitter (local, absolute): 89.155E-6 seconds
	   Jitter (rap): 0.545%
	   Jitter (ppq5): 0.650%
	   Jitter (ddp): 1.636%
	Shimmer:
	   Shimmer (local): 7.663%
	   Shimmer (local, dB): 0.669 dB
	   Shimmer (apq3): 3.656%
	   Shimmer (apq5): 5.658%
	   Shimmer (apq11): 7.601%
	   Shimmer (dda): 10.969%
	Harmonicity of the voiced parts only:
	   Mean autocorrelation: 0.897243
	   Mean noise-to-harmonics ratio: 0.174640
	   Mean harmonics-to-noise ratio: 12.821 dB
      
	Sub ReadFiles()
	    Dim myFile As Variant
	    Dim f As Variant
	    
	    ChDir "C:\"
	    myFile = Application.GetOpenFilename( _
	         FileFilter:="テキストファイル (*.txt; *.*),*.txt; *.*", _
	         MultiSelect:=True)
	    
	    If IsArray(myFile) Then
	        For Each f In myFile
	            Process_File (f)
	        Next
	    Else
	      If myFile <> False Then
	        Process_File (myFile)
	      End If
	    End If
	End Sub

	Function Process_File(fileName As String)

	' MsgBox "以下のファイルを追加:" + fileName

	Dim intFF As Integer            ' FreeFile値
	Dim strREC As String            ' 読み込んだレコード内容
	Dim GYO As Long                 ' 収容するセルの行

	' 1行目生成
	Cells(1, 1) = "ファイル名"
	Cells(1, 2) = "Jitter (ppq5) (%)"
	Cells(1, 3) = "Shimmer (apq5) (%)"
	Cells(1, 4) = "Mean harmonics-to-noise ratio (dB)"

	' 空行検索
	Dim Count As Long
	Count = 2
	Do Until Cells(Count, 1) = ""
	  Count = Count + 1
	Loop

	Cells(Count, 1) = Dir(fileName)
	intFF = FreeFile
	Open fileName For Input As #intFF
	GYO = 1
	Do Until EOF(intFF)
	  Line Input #intFF, strREC
	  If InStr(strREC, "Jitter (ppq5)") > 0 Then
	    Cells(Count, 2) = extractStr(strREC, "Jitter (ppq5): ", "%")
	  End If
	  If InStr(strREC, "Shimmer (apq5)") > 0 Then
	    Cells(Count, 3) = extractStr(strREC, "Shimmer (apq5): ", "%")
	  End If
	  If InStr(strREC, "Mean harmonics-to-noise ratio") > 0 Then
	    Cells(Count, 4) = extractStr(strREC, "Mean harmonics-to-noise ratio: ", " dB")
	  End If
	  GYO = GYO + 1
	Loop
	Close #intFF

	ProcessFile = Temp
	End Function

	Function extractStr(rngValue As String, strDel1 As String, strDel2 As String)
	Dim startNum As Integer, endNum As Integer

	startNum = InStr(rngValue, strDel1) + Len(strDel1) - 1
	endNum = InStr(startNum + 1, rngValue, strDel2)

	    If startNum <> 0 And endNum <> 0 Then
	        startNum = startNum + 1
	        extractStr = Mid(rngValue, startNum, endNum - startNum)
	    Else
	        extractStr = ""
	    End If

	End Function
      

以下のように収集される。

ファイル名Jitter (ppq5) (%)Shimmer (apq5) (%)Mean harmonics-to-noise ratio (dB)
info.txt0.655.65812.821
...

配列を使った方法

項目が多い場合は配列を使うと良い。

	Sub ReadFiles()
	    Dim myFile As Variant
	    Dim f As Variant
	    
	    ChDir "C:\"
	    myFile = Application.GetOpenFilename( _
	         FileFilter:="テキストファイル (*.txt; *.*),*.txt; *.*", _
	         MultiSelect:=True)
	    
	    If IsArray(myFile) Then
	        For Each f In myFile
	            Process_File (f)
	        Next
	    Else
	      If myFile <> False Then
	        Process_File (myFile)
	      End If
	    End If
	End Sub

	Function Process_File(fileName As String)

	' MsgBox "以下のファイルを追加:" + fileName

	Dim intFF As Integer            ' FreeFile値
	Dim strREC As String            ' 読み込んだレコード内容
	Dim GYO As Long                 ' 収容するセルの行

	Dim headList As Variant
	headList = Array( _
	"Median pitch: ", " Hz", _
	"Mean pitch: ", " Hz", _
	"Standard deviation: ", " Hz", _
	"Minimum pitch: ", " Hz", _
	"Maximum pitch: ", " Hz", _
	"Jitter (local): ", "%", _
	"Jitter (local, absolute): ", " seconds", _
	"Jitter (rap): ", "%", _
	"Jitter (ppq5): ", "%", _
	"Jitter (ddp): ", "%", _
	"Shimmer (local): ", "%", _
	"Shimmer (local, dB): ", " dB", _
	"Shimmer (apq3): ", "%", _
	"Shimmer (apq5): ", "%", _
	"Shimmer (apq11): ", "%", _
	"Shimmer (dda): ", "%", _
	"Mean autocorrelation: ", "", _
	"Mean noise-to-harmonics ratio: ", "", _
	"Mean harmonics-to-noise ratio: ", " dB" _
	)

	' 1行目生成
	Cells(1, 1) = "ファイル名"

	Length = UBound(headList) - LBound(headList) + 1
	For I = 0 To (Length / 2) - 1
	  Cells(1, I + 2) = headList(I * 2) + headList(I * 2 + 1)
	Next I

	' 空行検索
	Dim Count As Long
	Count = 2
	Do Until Cells(Count, 1) = ""
	  Count = Count + 1
	Loop

	Cells(Count, 1) = Dir(fileName)
	intFF = FreeFile
	Open fileName For Input As #intFF
	GYO = 1
	Do Until EOF(intFF)
	  Line Input #intFF, strREC
	   For I = 0 To (Length / 2) - 1
	     If InStr(strREC, headList(I * 2)) > 0 Then
	       Dim str1 As String
	       str1 = headList(I * 2)
	       Dim str2 As String
	       str2 = headList(I * 2 + 1)
	       Cells(Count, I + 2) = extractStr(strREC, str1, str2)
	     End If
	   Next I
	  GYO = GYO + 1
	Loop
	Close #intFF

	ProcessFile = Temp
	End Function

	Function extractStr(rngValue As String, strDel1 As String, strDel2 As String)
	Dim startNum As Integer, endNum As Integer

	startNum = InStr(rngValue, strDel1) + Len(strDel1) - 1
	endNum = InStr(startNum + 1, rngValue, strDel2)

	If startNum <> 0 And endNum <> 0 Then
	    startNum = startNum + 1
	    extractStr = Mid(rngValue, startNum, endNum - startNum)
	    If strDel2 = "" And startNum <> 0 Then
	      extractStr = Mid(rngValue, startNum, Len(rngValue))
	    End If
	Else
	    extractStr = ""
	End If

	End Function
      
If you can read this, you're too close.

I have much more books than I can put on my night-stand. Books that are on my
night-stand are quickly accessible (when I'm in bed, that is), and books on
the shelf are not (I hate getting up from the cozy, warm, bed). So, when I
suddenly feel like reading a book that is not on the night- stand, I have no
choice but to go to sleep. In the morning, I wake up and always find the book
I wanted next to the bed! As it turns out, when I was asleep, another process,
known as "sleepwalkd" got me the book I wanted. Also, when my nightstand
already has too many books on it, The sleepwalk process moves one of the books
- the one I'm least likely to want to read next - back to the shelf.

Last month, four Europeans with weird names decided to mess around with my
book-reading system. One called Alan decided that in some cases I should move
*all* my books to the shelf, go to bed without any books the same night, and
instead fill the nightstand with crap. And if somehow all my shelves are full
I should just burn one at random (if it burns the whole shelf, or the wrong
shelf, who cares).
Another one, called Andrea, decided that I should redesign my whole
sleepwalking routine according to his master-plan. However, this made my
sleepwalking become so strange, that people were hesitant to call me "stable"
any more. Alan thought my new sleepwalking was a sure sign of be not being
stable.
But then a third European, Linus, finally made a judgment-call, and decided
that I was stable, even with Andrea's new sleepwalking routine. He then told
yet another European, Marcello, that from now he's resposible for keeping me
stable. I thought it was my shrink's resposibility, but Marcello said no, that
now that he finally has some responsibility he's not going to just give it up.

    -- Nadav Har'El
    -- Hackers-IL Message No. 1,408 ( http://tech.groups.yahoo.com/group/hackers-il/message/1408 )


Powered by UNIX fortune(6)
[ Main Page ]