• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:矩形範囲の複数列を縦1列に並べ替えVBA(続))

矩形範囲の複数列を縦1列に並べ替えVBA(続)

eden3616の回答

  • ベストアンサー
  • eden3616
  • ベストアンサー率65% (267/405)
回答No.7

遅くなりました。 修正、最適化を行った最終のコードを最後に記載しております。 現状において、下記の不明な点がありますので、併せてご確認ください。 ■データパターンの出力順番について (1)元データエリアA,B → パターン3 (2)並べ替えエリアE1,J150 → パターン1 (3)タブ貼り付けエリアN1:T150 → パターン2 とのことですので 「パターン1、2、3」の順番で区切り記号「******」により出力するということでしょうか? 過去質問を読み返したところ >ただ、NTデータがBCの前になってしまっていたのでコメントをたよりに入れかえました。 と記述されており、ご提示されているコードからも「パターン1、3、2」の順になっているようですが。 現在は「パターン1、3、2」の順でコードを記述しておりますので、ご確認の上修正願います。 ■パターン3について いままでB,Cで処理を行ってきましたが、A,Bに変更いたしました。 変更される場合はコード内の「'(1)A,B列をタブ区切りでテキストデータへ出力」において 「"A"」、「"B"」の箇所を変更してください。 今までB,Cで行っていたときですが、1行目から「B列の最終行」までの範囲で、 「B列が空白以外」であれば「B列とC列をタブで結合して出力」しておりました。 今回、A,B列の最終行のうち、最終行が多い方をデータ範囲の最終行として選定し、 A,B列を結合したものが空白以外であれば、テキストデータとして出力しています。 ■データについて すでにご覧いただいたかと思いますが、ヒントとしてプロフィールを再度ご確認願います。 ■VBAコード Sub action() '型宣言 Dim st As String, ed As String Dim stcol As Long, edcol As Long Dim strow As Long, edrow As Long Dim retu As Long, gyou As Long Dim fname As String, tpath As String, dpath As String '◆ Dim fcnt As Long, r_max As Long Dim i As Long, j As Long '★ Dim srt As String, word As String '★ Dim retu_s As Variant, retu2_s As Variant '★ Dim myRng As Range '★ Dim ngs As Variant, ng As Variant '★ Dim objFileSys As Object, objTS As Object '★ 'ファイルの出力先 'dpath = "H:\■DATA\DATAB" dpath = ThisWorkbook.Path 'データの範囲、取得列の指定 st = "E1" ed = "O150" Set myRng = Range("E1:K150") '★ srt = "E,M,F,G,L,N,O" '★ 'セルアドレスより各行列番号を取得 stcol = Range(st).Column edcol = Range(ed).Column strow = Range(st).Row edrow = Range(ed).Row 'セル範囲が選択中の場合 If Selection.Count > 1 Then stcol = Selection(1).Column edcol = Selection(Selection.Count).Column strow = Selection(1).Row edrow = Selection(Selection.Count).Row End If '出力先のファイル名を処理 If Cells(strow, stcol).Text = "" Then fname = "不明(" & Cells(strow, stcol).Address & ")" Else fname = Cells(strow, stcol).Text End If ngs = Split("■,\,/,:,*,?,"",<,>,|", ",") For Each ng In ngs fname = Replace(fname, ng, "#") Next If Dir(dpath, vbDirectory) = "" Then MsgBox "パスが不正です" & vbCrLf & vbCrLf & dpath '◆ Exit Sub End If tpath = dpath & "\" & fname & ".txt" Do Until Dir(tpath) = "" fcnt = fcnt + 1 tpath = dpath & "\" & fname & "_" & fcnt & ".txt" Loop '///// テキスト書き出し処理 ///// 'テキストファイルを新規作成 Set objFileSys = CreateObject("Scripting.FileSystemObject") Set objTS = objFileSys.CreateTextFile(tpath) '(2)1列に指定した列順で出力(パターン1) '列方向にループ retu_s = Split(srt, ",") '★ For Each retu2_s In retu_s '◆ retu = Range(retu2_s & "1").Column '★ '行方向にループ For gyou = strow To edrow If Cells(gyou, retu).Text <> "" Then '◆ If Left(Cells(gyou, retu).Text, 1) <> "■" Then '★ objTS.WriteLine Cells(gyou, retu).Text End If '★ End If Next gyou Next '◆ objTS.WriteLine "****************************************************" '(1)A,B列をタブ区切りでテキストデータへ出力(パターン3) r_max = WorksheetFunction.Max( _ Range("A" & Rows.Count).End(xlUp).Row, _ Range("B" & Rows.Count).End(xlUp).Row) '★ For i = 1 To r_max '◆ If Range("A" & i).Text & Range("B" & i).Text <> "" Then '◆ objTS.WriteLine Range("A" & i).Text & vbTab & Range("B" & i).Text '◆ End If Next i objTS.WriteLine "***************************************************" '(3)矩形範囲をタブ区切りでテキストデータ出力(パターン2) Dim flag As Integer For j = 1 To myRng.Rows.Count word = "" flag = 0 For i = 1 To myRng.Columns.Count If myRng.Cells(j, i).Value <> "" Then flag = flag + 1 End If word = word & myRng.Cells(j, i).Value If i < myRng.Columns.Count Then word = word & vbTab Next i If flag > 0 And myRng.Cells(j, 1).Value <> "" Then objTS.WriteLine word Next j 'テキストファイルを閉じる objTS.Close MsgBox tpath & vbCrLf & "に出力しました" End Sub

noro6857
質問者

お礼

いつもながら貴重な時間をさいていただいてありがとうございます。 ◆データパターンの出力順番について パターンについては私も混乱しちゃっているのですが、 最初に並び替え、次に元データエリアの貼り付け、最後に矩形エリアの貼り付けということですので、ご指示のとおりも「パターン1、3、2」の順ですね。 ■パターン3について 実は出力フォームは結局同じなのですが、元データのフォームが色々あって、それにあわせて列の関数をその都度はめこんでおりそのフォームごとに集計方法を色々教えていただいていました。 今回一部統一しようとしている最中なのですが、 そのため当初の質問では、データ列がBとC(AはNoが入れてある)のフォームでの方法ですすめていたと思います。 現在もそのフォームも残っているためBCの場合もあり、修正しながら動作させたいと思っています。 ■データについて ちょっと意味が…? ■VBAコード これで問題なく出力できました。ありがとうございました。 なお、End Subの前に Application.Dialogs(xlDialogOpen).Show "H:\SDTXT\*.xlsm" ThisWorkbook.Close False を入れています。 これをこのBookの所在Passにしたい場合 ThisWorkbook.Pathにすればいいでしょうか。 なおあわせてお聞きしておきたいのですが、前述のとおり元データによる集計方法がいくつかパターンがあるため、それを今回統一フォームにしているのですが、集計方法にあわせて actionや action3、あるいはそれ以外のVBAをボタンをいくつか作ってフォーム毎に選択しています。 集計パターンにルールがあるのでフォームが統一できればたぶんactionの中でもその書き方をすれば可能のような気がしますが、今回はとりあえず既存のものを使い分けたいと思っています。 これをcall等を使ってひとつのボタンにすることは可能でしょうか。 具体的には A1の文字列の末尾5文字で判定して 「SD411,SD418,SD425」のときはVBA-1を呼び出す 「SD409」のときはVBA-2を呼び出す 「SD426」のときはVBA-3を呼び出す その他のときはVBA-4を呼び出す といった具合です。

noro6857
質問者

補足

■データについて わかりました。

関連するQ&A

  • 複数の列を繋げてA列に入れたい VBA

    aaa aaa  bbb aaa  bbb  ccc aaa (A列にaaa、B列にbbb、C列にcccが入ってます) と言うデータがあるのですが 全てA列に入れて aaa aaabbb aaabbbccc aaa としたいです。 ・最終列は必ずしもCではないのです。(Dの場合もEの場合もある) ・最終行も変化します。 Sub 分かれてる列を繋げる() Dim Col As Long Dim Row As Long For Row = 1 To Range("a65536").End(xlUp).Row   For Col = 1 To Cells(Row, 256).End(xlToLeft).Column    Cells(Row, 1) = Cells(Row, 1) & Cells(Row, 2) & Cells(Row, 3)    Next Col Next Row End Sub をやってみましたが、 aaa aaabbbbbb aaabbbcccbbbcccbbbccc aaa となってしまい、 欲しい結果とは違くなってしまいます。

  • VBA最終列の取得/不規則な処理

    VBAにて、最終列の取得ができません。 また、繰り返し処理を3列処理、step5、3列処理、step5…と繰り返し行う方法もご教授いただきたいです。 エクセルはo365を使用しております。 ①最終列の取得 実際は300列近くの表になります。 最終行は取得できたのですが、最終列がなぜかエラーも出ず、処理が行われません。 ②不規則な繰り返し処理 画像の水色部分のみ処理を行いたいです。 3列処理と記載したのですが、セル結合しているので、考え方が合っているのかも不明です。 塗りつぶされているセル一つ一つに処理を行いたいです。 また、行列共に可変します。 実行したいマクロは、選択したブックのSheets(1)の表の中の水色に入力されている文字列が「1」か「2」か判断するというものです。 「1」と入力されていれば → 別ブックのA1セルに1をカウント 「2」と入力されていれば → 別ブックのB1セルに1をカウント ※水色セルは参考で用意したものなので、実際は塗りつぶしされていません。 ※空白のセルもあります ①②の解消法のご教授をよろしくお願い致します。 =============================================== Option Explicit Sub kurikaeshi() Dim retu As Long, gyou As Long Dim File As Workbook Set File = Workbooks("test.xlsx") Dim ws1 As Worksheet, ws2 As Worksheet Set ws1 = File.Sheets(1) Set ws2 = ThisWorkbook.Sheets(1) Workbooks.Open FileName:=ThisWorkbook.Path & "/" & File For retu = 2 To ws1.Cells(4, ws1.Columns.Count).End(xlToLeft).Column 'ここが処理されません For gyou = 4 To ws1.Cells(ws1.Rows.Count, 2).End(xlUp).Rows If ws1.Cells(gyou, retu).Value = "1" Then ws2.Range("A1") = ws2.Range("A1") + 1 If ws1.Cells(gyou, retu).Value = "2" Then ws2.Range("B1") = ws2.Range("B1") + 1 End If Else Exit Sub End If Next gyou Next retu End Sub

  • Excel VBA 配列による複数セルへの入力

    VBA初心者です.よろしくお願いいたします. 用語の読みを自動で振るシートを作成しているのですが,Do Loop部分が一行ずつの入力となっていて,時間がかかっています. これを配列等の方法を用いて高速化したいと思って,試行錯誤したのですが,うまくいきません. 何卒お教えくださいますようお願いいたします. 用語の読みを生成する手順ですが, 1.シート1に用語をペーストする 2.ペーストされた用語をシート2にある用語のDB(用語と読みが入力されています.重複レコードなし)にコピー 3.コピーされたシート2をピボットにして個数が2以上あった場合,その用語と読みを返します. 4.Do Loopで最初にヒットした用語に戻るまでループ となっています. 3までの手順に修正の必要はないのですが,4の手順でかなり時間をロスしております. ここを配列等の方法で一度に書き込むことができればと思っています. Sub test() i = 8 L_Row04 = 180188 Dim S1 As Worksheet '読みを振る用語をペーストするシート Dim S2 As Worksheet '読み用の用語のDB Dim S3 As Worksheet 'ピボット Dim L_Row01 As Long 'S1にペーストされた用語の最下行 Dim L_Row02 As Long 'S1の用語をs2にペーストしたときの最下行 Dim L_Row03 As Long 'ピボットの用語の最下行 Dim Rng01 As Range 'S1にペーストされた用語の範囲 Dim Rng02 As Range 'S2にペーストされた用語の範囲 Dim Rng03 As Range 'ピボットの範囲 Dim Str01 As Variant 'ピボットで2以上あったときの用語 Dim Str02 As Variant 'ピボットで2以上あったときの読み Dim firstcell As Range Dim Foundcell01 As Range Set S1 = Worksheets(1) Set S2 = Worksheets(2) Set S3 = Worksheets(3) S1.Activate L_Row01 = S1.Cells(Rows.Count, 2).End(xlUp).Row L_Row02 = S2.Cells(Rows.Count, 3).End(xlUp).Row Set Rng01 = S1.Range(Cells(i, 2), Cells(L_Row01, 2)) Rng01.Copy Destination:=S2.Cells(L_Row02 + 1, 2 + 1) S3.PivotTables("ピボットテーブル2").RefreshTable S2.Activate L_Row02 = S2.Cells(Rows.Count, 3).End(xlUp).Row Set Rng02 = S2.Range(Cells(L_Row04, 3), Cells(L_Row02, 3)) Rng02.Delete S3.Activate L_Row03 = S3.Cells(Rows.Count, 2).End(xlUp).Row Set Rng03 = S3.Range(Cells(4, 2), Cells(L_Row03, 2)) For Each a In Rng03 If a >= 2 And a.Offset(0, -1).Value <> "(空白)" And a.Offset(1, -1).Value <> "(空白)" Then Str01 = a.Offset(0, -1) Str02 = a.Offset(1, -1) S1.Activate Set Foundcell01 = Rng01.Find(What:=Str01, searchorder:=xlByRows, LookIn:=xlValues, lookat:=xlWhole) Do Selection.Offset(0, 1).Value = Str02 Selection.Offset(0, 2).Value = "●" Loop Until ActiveCell.Address = firstcell.Address End If End If Next End Sub

  • VBA 空白表示させたい

    教えて頂いたVBAなのですが Sub Macro1() Dim Ws01 As Worksheet Dim Counter As Long, i As Long, j As Long Dim INP As String Set wS = Worksheets("Sheet4") wS.Cells.ClearContents If Selection(Selection.Count).Row <> 2 Then Exit Sub Counter = 0 For i = 3 To ActiveSheet.UsedRange.Rows.Count INP = "" For j = Selection(1).Column To Selection(Selection.Count).Column If Cells(i, j) = 1 Then INP = INP & Cells(2, j) & "," End If Next j If INP <> "" Then Counter = Counter + 1 wS.Cells(Counter, "A") = Left(INP, Len(INP) - 1) End If Next i End Sub ---------------------------------------------------------------------- g      h       i      j パセリ クレソン メキャベツの葉 ごぼう 1      1             1 1                    1 1行目 パセリ,クレソン,メキャベツの葉 2行目  3行目 パセリ,メキャベツの葉 と、2行目は詰めずに空白表示したいです。 どこをどうすればできますか?

  • VBAで複数ファイルのページ数出力

    Win10のOffice365のExcelを使用しています。 GetOpenFilenameで選択した複数のExcelファイルのファイル名+印刷ページ数を マクロを実行したファイルに出力するというマクロを作成しました。 マクロを実行する度に既存データがあれば追加されていくようにしたいのですが、上手くいきません。 それどころか、実行時も複数ファイル選択したにも関わらず、 1ファイルのデータしか出力されない状態です。 実行後のイメージは添付ファイルの通りです。 (A1、A2はデフォルトで入力しています。) 勉強を始めたばかりなので改善点もあれば、教えて頂きたいです。 よろしくお願い致します。 ================================================= Option Explicit Sub pagecount() Dim Page As Long, cnt As Long, xlcnt As Long Dim fs As Variant, path As Variant Dim Fname As String Dim i As Integer Dim wb1 As Workbook, wb2 As Workbook Dim sh As Worksheet With CreateObject("WScript.Shell") .CurrentDirectory = ThisWorkbook.path End With fs = Application.GetOpenFilename(filefilter:="Microsoft Excelブック,*.xls*", MultiSelect:=True) If IsArray(fs) Then For Each path In fs Set wb1 = Workbooks.Open(path, , True) Set wb2 = ThisWorkbook Do Until (Fname = "") Page = 0 For Each sh In wb1.Worksheets Page = Page + sh.PageSetup.Pages.Count Next sh xlcnt = Cells(Rows.Count, 1).Row cnt = Cells(xlcnt, 1).End(xlUp).Row If wb2.ActiveSheet.Cells(cnt, 1).Value <> "" Then wb2.ActiveSheet.Cells(cnt, 1).Value = Fname wb2.ActiveSheet.Cells(cnt, 1).Offset(0, 1) = Page wb1.Close savechanges:=False Fname = Dir() cnt = cnt + 1 End If Loop Next path End If End Sub

  • EXCEL VBA データのある範囲の特定が悪い?  

    アンケート調査票を簡単につくために、下のようなマクロを教えていただいたのですが、もとデータ項目の参照範囲がセルのB5より上にあるもの(空白の場合も)も項目としてしまっているようなので、どこを手直しすればいいのか、すみませんが教えてください。 Sub test() '定数の設定 Const strInputSheet As String = "Sheet1" Const lngInputRow As Long = 5 Const lngInputCol As Long = 2 Const strOutputSheet As String = "Sheet2" Const lngOutputCol As Long = 3 Const lngOutputRow As Long = 4 Const strMessageA As String = " は " Const strMessageB As String = " に対してどの位影響があると思いますか?" '定義 Dim lngMaxRow As Long Dim lngCountA As Long Dim lngCountB As Long Dim strA As String Dim strB As String Dim lngRow As Long '項目数を把握 Sheets(strInputSheet).Select Cells(ActiveSheet.Rows.Count, lngInputCol).Select Selection.End(xlUp).Select lngMaxRow = Selection.Row 'B列のデータ最終行を取得 lngRow = lngOutputRow '出力開始行の設定 '項目Aをなめる For lngCountA = lngInputRow To lngMaxRow  strA = Cells(lngCountA, lngInputCol).Value '項目Aの取得  '項目Bをなめる  For lngCountB = 1 To lngMaxRow   If lngCountA <> lngCountB Then '項目Aと項目Bが同じときはここは処理しない    strB = Cells(lngCountB, lngInputCol).Value '項目Bを取得    Sheets(strOutputSheet).Cells(lngRow, lngOutputCol).Value = strA & strMessageA & strB & strMessageB '文字列を結合    lngRow = lngRow + 1 '改行する   End If  Next lngCountB Next lngCountA End Sub

  • マクロ 入力する文字に色を付けたい

    Sub CountUp(ByVal mCol1 As String, mCol2 As String) Dim LastRow1 As Long Dim LastRow2 As Long Dim mRow As Long With Sheets("プレーヤー") LastRow1 = .Cells(Rows.Count, mCol1).End(xlUp).Row LastRow2 = .Cells(Rows.Count, mCol2).End(xlUp).Row If LastRow1 > LastRow2 Then mRow = LastRow1 Else mRow = LastRow2 End If If LastRow1 = 1 Then LastRow1 = 2 End If .Cells(mRow + 1, mCol1).Value = .Cells(LastRow1, mCol1) + 1 End With End Sub このコードに文字の色の指定をしたいです Selection.Font.ColorIndex = 3を入れたら赤色文字で入力できるかなと思ったのですがうまくいきませんでした(エラーにはならないのですが、色が付かなかったです)

  • VBAで文字列のカウントがうまくいかない・・・です

    Dim cnt As Long Dim i As Long Dim lastRow As Long For i = 1 to 20 step 2 lastRow = Cells(65536, i).End(xlUP).Row cnt = WorksheetFunction.CountIf(ActiveSheet.Range(Cells(10, i),Cells(lastRow, i), "お世話になっております")cnt = cnt + cnt Next Excelのセルを1列ずつ飛ばして列に「お世話になっております」が含まれたら件数をカウントしています。 そのカウント数が何故かリセットされてしまいます。 カウント数を足していきたいのですが・・・考え方自体が違うのでしょうか?

  • Excel VBA オートフィルの範囲指定

    Excel VBA で関数を入れたセルを最下行までコピー させたいのですが、範囲の指定がうまくできません。ごちゃごちゃ書きすぎて、よくわからなくなってしまいました。 実行してみたら、オートフィルのところでデバッグが出ました。 VBAはまだまだ初心者レベルです・・・ どこをどう直せばきちんと処理されるのか、どなたかお知恵をお貸しください。 (それと初めの定義は、Rangeで合ってるのでしょうか?) Sub sample() Dim MyCell1 As Range Dim MyCell2 As Range Dim MyCell3 As Range Dim MyCell4 As Range Dim MyCell5 As Range Set MyCell1 = Cells(5, Range("4:4").Find(what:="○○", searchorder:=xlByColumns).Offset(1, 1).Column) Set MyCell2 = Cells(5, MyCell1.Offset(0, 2).Column) MyCell1.Select Selection.Formula = "=$A5-" & MyCell2.Address(False, True) Set MyCell3 = Cells(5, MyCell1.Offset(0, -1).Column) Set MyCell4 = Cells(5, Cells(5, Columns.Count).End(xlToLeft).Column) Set MyCell5 = MyCell1.Offset(0, 1) MyCell5.Select Selection.Formula = "=" & MyCell3.Address(False, True) & "-" & MyCell4.Address(False, True) Range(MyCell1, Cells(5, MyCell1.Offset(0, 1).Column)).Select Selection.AutoFill Destination:=Cells(Cells(5, MyCell1.Column), Cells(Cells(Rows.Count, 1).End(xlUp).Row, MyCell5.Column)), Type:=xlFillCopy End Sub ********************* 下のような表に関数を入力して最下行までコピーさせたいです。  | A | B | C | D | E | F | G | H | I | J | K | L | -------------------------------------------------------------------------- 4 | code | name | 7/1 | 7/2 | ○○ |    |    | code|name| 7/1 | 7/2| ○○ | 5 |10000|aaaaaa| 15  | 20 | 35  |     |    |10001|bbbbbb| 13 | 25 | 38 |                           ((                            )) F5に "=$A5-$H5" と数式を入れてcodeを比較し、G5に "=$E5-$I5"と入れて数量を比較する。 F列とG列の入力されている最下行まで数式をコピーする。 ※毎月日数が変わり、商品数も変わるので、A列・B列・4行目以外は全て可変。 WindowsXP Excel2003 です。 よろしくお願いいたします。

  • Excel VBA; 複数のループ処理

    ↓のようなコードがあります。 Dim i As Long, MaxRow1 As Long, MaxRow2 As Long MaxRow1 = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row MaxRow2 = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row For i = 1 To MaxRow1 Worksheets("Sheet1").Cells(i, 1).Value = i . Next i For i = 1 To MaxRow2 Worksheets("Sheet2").Cells(i, 1).Value = i . Next i これらを最大行の多いシートに合わせて、パフォーマンスを良くしたいと思います。 同様の処理をシート1、シート2で実施しているので纏めて記述したいです。 シート1、シート2に対する処理をサブルーチンにする方法しかありませんか? どなたかお願いします。 If MaxRow1 >= MaxRow2 Then For i = 1 To MaxRow1 Else For i = 1 To MaxRow2 End If Worksheets("Sheet1").Cells(i, 1).Value = i Worksheets("Sheet2").Cells(i, 1).Value = i . Next i