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

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

eden3616の回答

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

以前回答させて頂いたものです。 以下の変更箇所を修正してください。 ■変更箇所 (1)「'型宣言」内の最後(Dim fcnt As Longの後)に以下を追加 Dim i As Long Dim srt As String Dim retu_s As Variant (2)「'データの範囲~」の最後(ed = "R200"の後)に以下を追加 srt = "M,P,N" (3)「'列方向にループ」の最初(For retu = stcol To edcol)を削除 (4)(3)で削除した箇所(「'列方向にループ」と「'行方向にループ」の間)に以下を追加 retu_s = Split(srt, ",") For Each retu2_s In retu_s retu = Range(retu2_s & "1").Column (5)「'行方向にループ」の最後(Next retu)を以下に変更   (VBA処理的には「列」処理のループ最後) Next ■補足 (2)で指定した列順に取得して表示します。 M~R列を漏れなく半角カンマ「,」区切りで記述してください。 (上記コードでは提示して頂いたM、P、Nのみ取得されます) 手軽であるため、上記のような仕様にしましたが、 ExcelのソートのようにMPNの順で優先ソートして範囲内全てを書き出す場合は処理を別途考えます。

noro6857
質問者

お礼

ご回答いただけて光栄です。 質問欄のVBAは当初のもので途中修正していただいており、最終的に下記部分訂正して使用しております。全文記述すると長くなりますので修正箇所のみ書きます。 '型宣言に追加 Dim objFileSys As Object, objTS As Object Dim word As String Set objFileSys = CreateObject("Scripting.FileSystemObject") 'データの範囲(左上のセルと右下のセル)アドレスを指定 st = "E1" ed = "J150" Set myRng = Range("N1:T150") 以下の部分以降を書き換え Open tpath For Output As #1 '列方向にループ For retu = stcol To edcol ~ MsgBox tpath & vbCrLf & "に出力しました" End Sub 下記のように修正→ '///// テキスト書き出し処理 ///// 'テキストファイルを新規作成 Set objTS = objFileSys.CreateTextFile(tpath) '(1)E~J列を1列にテキストデータへ出力 '列方向にループ For retu = stcol To edcol '行方向にループ For gyou = strow To edrow If Cells(gyou, stcol).Text <> "" Then objTS.WriteLine Cells(gyou, retu).Text End If Next gyou Next retu '区切りをテキストデータへ出力 objTS.WriteLine "****************************************************" '(3)B,C列をタブ区切りでテキストデータへ出力 For i = 1 To Range("B" & Rows.Count).End(xlUp).Row If Cells(i, 2).Value <> "" Then objTS.WriteLine Cells(i, 2).Value & vbTab & Cells(i, 3).Value End If Next i '区切りをテキストデータへ出力 objTS.WriteLine "***************************************************" '(2)N~T列をタブ区切りでテキストデータへ出力 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 以上です。うっかり古いままのVBAで質問してしまいました。 今回の趣旨は1列に並べ替える部分(M1~I150)とそれをタブ用に貼り付けるフォーム(N1-T150)のデータがかなりかぶっているためひとつの表にしてしまいたいのですが、貼り付けフォームはそのままの順序にしておくとして、1列並べ替えはその中から、必要な列を抜き出せればいいと思っています。 もちろん現在でもデータのダブリさえ気にしなければ満足できる仕様となっています。 すなわちEからN列までデータ表を作り、最後のタブ貼り付け部分はE1~K150(従来のN1~T150に相当する部分)を対象とし、1列並び替えはM/E/F/N/H/G/I/Lの列を対象にこの順にしようというものです。 こんな感じでご理解いただけますでしょうか。

noro6857
質問者

補足

修正後のVBAでも、上記ご指示の変更で、必要列の抽出が問題なくできました。 色々修正していただいた後のVBAで影響が出るのを心配しましたが不要でした。 ありがとうございました。 なお、関連してですが、後半のタブ書き出しを単独でVBA処理しているのですが、(N~T列のみの抽出で列並び替え等不要)よくわからないためいただいたVBAから、 '///// テキスト書き出し処理 /////と '区切り(B列)をテキストデータへ出力 をはずしただけでそのまま運用して出力しています。 不要そうなのを削除したら動かなくなってしまっため、それ以外の記述はそのまま手をつけていませんので 関連のない記述もそのまま残っています。 不要部分を整理できればと思っています。 ※単にZ1~AF150を矩形でタプ抽出、テキスト生成のみです。 Sub action2() '型宣言 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 Dim fcnt As Long Dim objFileSys As Object, objTS As Object Dim word As String Set objFileSys = CreateObject("Scripting.FileSystemObject") 'データの範囲(左上のセルと右下のセル)アドレスを指定 st = "K1" ed = "P400" Set myRng = Range("Z1:AF400") 'セルアドレスより各行列番号を取得 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 dpath = ThisWorkbook.Path If Dir(dpath, vbDirectory) = "" Then Debug.Print "dpath = " & dpath MsgBox "パスが不正です" Exit Sub End If tpath = dpath & "\" & fname & ".txt" Do Until Dir(tpath) = "" fcnt = fcnt + 1 tpath = dpath & "\" & fname & "_" & fcnt & ".txt" Loop '///// テキスト書き出し処理 ///// 'テキストファイルを新規作成 Set objTS = objFileSys.CreateTextFile(tpath) '区切りをテキストデータへ出力 objTS.WriteLine "***************************************************" 'Set myRng = Range("N1:T150") '(2)N~T列をタブ区切りでテキストデータへ出力 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

関連する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