それわVBA案件ですね

エクセルVBAネタを書いています

鳥の飛来地をエクセルで集計したい2

みなさんこんにちわ。

 

和歌山県鳥類目録をエクセルで集計してみたい管理人ですが、

目録がまさかのPDFでできていて、試しに全コピペしてみたら、

表構造が保たれていないばかりか、PDFの表の各項目をどんな法則性で複数のセルに分割したのか理解不能なブツが出来上がってやや思考停止となりました。

 

<コレを全コピペしたら>

f:id:FukuCyndiP:20190908110943p:plain

 

<こうなりましたw>

f:id:FukuCyndiP:20190908140354p:plain

 


んが、

表の先頭項目になるべき行の最初の記述に "セル内の文字列は数字+半角スペースで始まる” の規則性発見したため、VBAで何とかなるんじゃね? 感が出てきました。

 

f:id:FukuCyndiP:20190908120526p:plain

 

 

でわ、これをどう料理しましょうか。

 

まずやらないといけないことは、PDFで見る表のすべての項目がA列に並んでしまっているので、これをPDFの表の形に近づけます。

 

つまり

エクセルワークシートでは

 番号、科名、種名、生態、備考(飛来地など)

 

の情報を1行にまとめることを目指します。

 

 

ここで、数字+半角スペースの法則性が生きてきます。

これにより、A列のどの行に含まれる情報が最初に来るべき情報であるかがはっきりするとともに、どこの行のセルまでを1行にまとめるべきかもわかることになります。

 

というわけで、次のような処理を作っていきます

1.セルの中身を左から走査して、左端から最初半角スペースまでの文字が数字となるセル(ヘッダーセル)を見つける

2.ヘッダーセルとその次のヘッダーセルのいっこ上のセルまでの情報を連結する

3.連結した文字列を新しいシートに順に並べる

 

どこからどこまでのセットは目録に記載されている鳥の種類数だけあるので、それぞれを配列に格納しながら、全体の処理を進めていくことにします。

f:id:FukuCyndiP:20190914001907p:plain

 

 

1.の処理コードはこんな感じ

 


0. Sub 文字列の先頭が番号なセルを配列化()

1.   Dim temp As Range
2.   Dim Arr() As Variant
3.   Dim i As Long

4.   With Worksheets("初期データ")
5.    For Each temp In .Range("A1:A1153")
6.     If IsNumeric(Left(temp.Value, InStr(temp, " "))) Then
7.      ReDim Preserve Arr(i)
8.      Set Arr(i) = temp
9  .       i = i + 1
10.        End If
11.      Next 
12.     End With
13.  End Sub

 

処理のご本尊は5-11行目になりますが、ポイントは

5行目: 走査対象データの入っている A1~A1153 セルをオブジェクトとしてVariant型変数tempへ順に入れて以降の処理を行うループ

6行目: tempの文字情報(.Value)の左から数えて半角スペースまでの文字列が数字(IsNumeric())か否かを判定

InStr(temp," ")はtempに代入された文字列を左から数えて何番目に半角スペースがあるかを返します

8行目: (6行目で数字=Trueなら) Rangeオブジェクトtempを配列に登録する(Setステートメントを使えばRangeオブジェクトであっても配列化できます)

 

因みに、IsNumeric()関数はString型の数字であっても、数字として認識してくれます

f:id:FukuCyndiP:20190908164059p:plain

 

実行してみる

 

f:id:FukuCyndiP:20190908165533p:plain



 確認のために配列に登録されたRangeオブジェクトのアドレスをArr().Addressで出力していますが、元データの先頭文字とそのあとに来る半角スペースで挟まれた部分が数字となっている(赤線付けた)セルアドレスがデバッグ出力されていますね。

 

これで処理1はおkですね。

 

 

 

処理に2についてはまた後日  ̄▽ ̄)ノシ