- ベストアンサー
ファイル名「1.jpg ~10.jpg~」のソート方法について
- エクセルのvbaを使って複数の写真ファイルを一気に貼り付けてJPEGに変換するプログラムを作成しています。しかし、ファイル名のソートがうまくいかず困っています。指定したフォルダのファイル名を取得し、それをリスト用のシートに出力し、使用者に必要なファイルを選択してもらうようにしていますが、ファイル名の順番が「1.jpg、10.jpg、2.jpg...」となってしまいます。汎用性を持たせつつ、ファイル名を正しくソートする方法はありますか?
- 写真ファイルを一気に貼り付けてJPEGに変換するプログラムの作成中に、ファイル名のソートについて困っています。現状では指定したフォルダのファイル名を取得してリスト用のシートに出力しているのですが、ファイル名の順番が正しく表示されません。例えば、「1.jpg、2.jpg、...、10.jpg」という順番でソートしたいのに、「1.jpg、10.jpg、2.jpg...」となってしまいます。この問題を回避する方法はありますか?
- エクセルのvbaを使って写真ファイルを一気に貼り付けてJPEGに変換するプログラムを作成していますが、ファイル名のソートに関して問題が生じています。現在、指定したフォルダのファイル名を取得してリスト用のシートに出力し、使用者に必要なファイルを選択してもらうようにしていますが、ファイル名の順番がうまくソートされません。具体的には、「1.jpg、10.jpg、2.jpg...」という順番になってしまいます。この問題を解決する方法はありますか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
Windows XP 以降、エクスプローラーのファイル表示に使われているソート ルールってことですよね。(マイクロソフトの直観的なソート) StrCmpLogicalW って API を使ってるっぽいです。 SortByIntuitiveFilename っていう関数を作ってみました。 文字列型の配列にファイル名の一覧を入れておいてこの関数に渡せばソートしてくれます。 一応テスト用のプロシージャ Sub Test() も載せておきます。 Option Explicit Declare Function StrCmpLogicalW Lib "SHLWAPI.DLL" (ByVal lpStr1 As String, ByVal lpStr2 As String) As Long Sub SortByIntuitiveFilename(ByRef aFiles() As String) Dim i As Long Dim j As Long Dim tmp As String 'Dim minIdx As Long 'Dim maxIdx As Long 'minIdx = LBound(aFiles) 'maxIdx = UBound(aFiles) For i = LBound(aFiles) To UBound(aFiles) For j = i To UBound(aFiles) If StrCmpLogicalW(StrConv(aFiles(i), vbUnicode), StrConv(aFiles(j), vbUnicode)) > 0 Then tmp = aFiles(i) aFiles(i) = aFiles(j) aFiles(j) = tmp End If Next Next End Sub Sub test() Dim strPath As String strPath = "e:\test" Dim fso As Scripting.FileSystemObject Dim fld As Scripting.Folder Set fso = New Scripting.FileSystemObject Set fld = fso.GetFolder(strPath) Dim fileNames() As String Dim cnt As Long cnt = fld.Files.Count ReDim fileNames(cnt - 1) Dim k As Long k = 0 Dim f As Scripting.File For Each f In fld.Files fileNames(k) = f.Name k = k + 1 Next Call SortByIntuitiveFilename(fileNames) End Sub
その他の回答 (2)
- imogasi
- ベストアンサー率27% (4737/17069)
ソートキーのためにシートの各行(ファイル名が入っている)の余分な空き列に、Format関数ででも、1や2を001,002に変換した文字列を作って持ち(12,23も012,023のようにする)、この列でエクセルでソートして、ソート後の結果を使えば良い、 作業列が嫌いなら配列に一時的にファイル名を持つ必要があるが、配列データのロジックも色々有り、テストも本来大変。 ーー エクセルではシートのセルにあるデータ(内容)でしかソートできない。色々悩んでよい方法がないか、など考えても無駄。 ーー ソートするルールは決っているのだ。それを勉強して、ユーザー(VBA内を作るもの)がそれに合うように修正ソートキーをどこかに作らざるをえないのだ。 ーーー ーを挟んでも質問尾ことは解決されないのでは。桁調節のスペースが許されないケースでは。
お礼
回答ありがとうございます! 「ーを挟んでも質問尾ことは解決されないのでは。桁調節のスペースが許されないケースでは。」 ハイフンとかいれた場合の質問をしても、質問箱では解決できないということですか? 又、format関数を用いた作業列を使うなら、ハイフンが邪魔で桁調整ができないということですかね。 format関数すら、この答えで知ったものですから私には難しいですが、桁調整の問題はNo.1番さんの答えで解決しました(ついでに作業列もありません) しかし、format関数を使った作業列という案も十分な有効な策なので、どちらがいいかは吟味させていただきます
- end-u
- ベストアンサー率79% (496/625)
仮にA2以下に書き出されたファイル名をソートする場合、 Sub try() Const MX As Long = 5 '取り敢えず各数値最大5桁の設定 Dim target As Range '並べ替え対象セル範囲 Dim r As Range 'Loop用 Dim rep As String 'Format関数用 Dim tmp As String '整形前Value Dim ret As String '整形後Text Dim s As String '文字1個 Dim ss As String '連続数値文字 Dim x As Long 'Len Dim p As Long '桁数記憶用 Dim i As Long Dim j As Long Application.ScreenUpdating = False '並べ替え対象のセル範囲をセット。 'サンプルとして(A2:A列最終行) Set target = Range("A2", Cells(Rows.Count, 1).End(xlUp)) rep = String(MX, "0") For Each r In target tmp = r.Value x = Len(tmp) + 1 '整形後Text長をMAXで設定 ret = Space(x * MX) p = 0 j = 1 '1文字ずつLoop For i = 1 To x s = Mid$(tmp, i, 1) If IsNumeric(s) Then '数値だったら連続数をCountして連結 p = p + 1 ss = ss & s Else If p > 0 Then 'Format関数で桁合わせて連結 Mid$(ret, j, MX) = Format$(ss, rep) j = j + MX p = 0 ss = Empty End If '数値以外を連結 Mid(ret, j, 1) = s j = j + 1 End If Next '整形後Textをふりがなにふる r.Phonetic.Text = Left$(ret, j) Next 'ふりがなSort target.Sort Key1:=target.Item(1), Order1:=xlAscending, _ Header:=xlNo, OrderCustom:=1, _ MatchCase:=False, Orientation:=xlTopToBottom, _ SortMethod:=xlPinYin Application.ScreenUpdating = True Set target = Nothing End Sub ..こんな感じで。 地道Loop案なのでちょっと遅いかもしれませんが。
お礼
ありがとうございます! ふりがなを設定すると、エクセルの既存の機能で、並び替えできるようになるんですか・・・ これは知らなかった。ふりがなってバカにできないですねぇ 勉強になります
お礼
ありがとうございます! これは、便利ですね。 StrCmpLogicalW という関数の仕様が見つからなかったので、ちょっと試してみた感じだと、XPのファイルシステムを使って二つのファイル名が降順だと1、同じなら0、昇順なら-1を返すってかんじっぽいですね。 これなら、XPのエクスプローラーとまったく同じ順序になるので、違和感もなくなると思います。 ありがとうございましたー