• 締切済み

一行の中から複数の値を抜き出す。

エクセルを使用し、画像の上側のような表を作っています。説明の為、短くしてありますが実際のファイルは横にずらーっと日付が並んでおり、一年で一つのファイルです。月ごとにタブを設定しています。 部屋番号も下に10ほど並んでおります。 画像を一枚に収めるために、表を二つ入れてありますが、実際にはこの二つの表は別々のファイルにしたいです。(上側の表のファイル名を名簿.xlsxlとします) 名簿.xlsxを別のエクセルファイル(宿泊一覧.xlsx)から読み込んで、 名簿.xlsxから宿泊者名を自動で抜き出して、滞在日数や泊数を計算させて表を作成させることは可能でしょうか? 画像を一枚に収めるために、表を二つ入れてありますが、実際にはこの二つの表は別々のファイルにしたいです。 名簿.xslxをどんどん更新すると、宿泊一覧にも名前が更新されるようにしたいのですが、関数だけではできないものなんでしょうか? VBAはよくわからないので、できれば関数でやるやり方を教えて頂ければありがたいです。

みんなの回答

  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.9

ANo.8です。 ごめんなさい、ミスがありました。 「End Sub」の2つ上の行を以下の様に修正してください。 誤:Worksheets(1).Range("A2:C" & nCount) = vData2 ↓ 正:Worksheets(1).Range("A2:C" & nCount + 1) = vData2

全文を見る
すると、全ての回答が全文表示されます。
  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.8

いっぱい回答が付いているのでいまさら感が有りますが、VBAでやる場合です。 前提は、 ・宿泊者名はかならず「様」が付く ・月跨ぎは前の月の最終日は「→」(月末にチェックインの場合は宿泊者名)で終わり、次の月の1日は「→」または「退」で始まる ・年跨ぎは無い。 ・名簿のシート名は「4月」~「3月」で、12か月分ちゃんとある 宿泊一覧.xlsm に以下のコードを入れて実行してください。 宿泊一覧ブックの1枚目のシートのA2以下に名前とイン、アウトを貼り付けます。 日数や泊数はExcelの演算式で出してください。 Sub Sample()   Dim vData()     nCount = 0 '宿泊総回数   nLastRow = 5 '使用している最終行(実際の名簿に合わせて変える)      Application.ScreenUpdating = False   Workbooks.Open Filename:="C:\名簿.xlsx" '実際の保存場所に合わせて修正   With ActiveWorkbook     For i = 3 To nLastRow '列ごとに処理(データは3行目から有るものとしています)       For j = 0 To 11 '「4月」~「3月」までの月別シートごとに処理         sShtName = Month(DateAdd("M", j, "4/1")) & "月" '対象シート名         For k = 2 To 32 '日にち毎にチェック(手抜きで2月も小の月も31日分チェック)           sData = .Sheets(sShtName).Cells(i, k).Value           Select Case True           Case sData Like "*様" 'セルの値に「様」を含んでいればチェックイン             ReDim Preserve vData(2, nCount)             vData(0, nCount) = sData             vData(1, nCount) = .Sheets(sShtName).Cells(1, k).Value                      Case sData = "退" 'セルの値が「退」ならチェックアウト             vData(2, nCount) = .Sheets(sShtName).Cells(1, k).Value             nCount = nCount + 1           End Select         Next k       Next j     Next i     .Close   End With   '行列を入れ替えて宿泊一覧に貼り付け   vData2 = Application.WorksheetFunction.Transpose(vData)   Worksheets(1).Range("A2:C" & nCount) = vData2   Application.ScreenUpdating = True End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.7

親の仇のように顔を出してごめんなさい。 一番大切な下準備を書き忘れていました。 「名簿」Bookの最後の「作業用」Sheetの1行目にシリアル値を入れるコトを記載し忘れていました。 「名簿」Bookの13番目「作業用」SheetのA1セルに 4/1 と入力 → ホームタブの左上のΣマークの下の「フィル」のアイコン(箱の中に↓の印があるアイコン)をクリック → 連続データの作成 → 「行」・「日付」が選択されている状態で 「増加単位」は「日」・「増加値」は「1」となっているコトを確認し 「停止値」に 2014/3/31 と入力しOK これで1行目に来年の3月31日までのシリアル値が表示されます。 これをやっていないと全く意味のないコードになってしまいます。 ほんとぉ~!っに何度もごめんなさいね。m(_ _)m

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.6

何度もごめんなさい。 前回のコードを↓に変更してください。 前回は余計なコトをしていたようで、「宿泊一覧」Bookを開くコードを入れたつもりですが、 実際は保存場所等(フルパス)を記載しなければならないはずですので、 「宿泊一覧」Bookは開いた状態で↓のマクロを実行してください。 (おそらく前回のコードではエラーになってしまうと思います) Sub 名簿更新2() 'この行から Dim i As Long, j As Long, k As Long, endRow As Long, endCol As Long Dim c As Range, wS1 As Worksheet, wS2 As Worksheet Workbooks("名簿").Activate Set wS1 = Worksheets("作業用") Set wS2 = Workbooks("宿泊一覧").Worksheets("Sheet1") endRow = wS2.Cells(Rows.Count, "A").End(xlUp).Row If endRow > 1 Then Range(wS2.Cells(2, "A"), wS2.Cells(endRow, "C")).ClearContents End If endRow = wS1.UsedRange.Rows.Count If endRow > 1 Then wS1.Rows(2 & ":" & endRow).ClearContents End If For k = 1 To 12 With Worksheets(k) Set c = wS1.Rows(1).Find(what:=.Cells(1, "B"), LookIn:=xlValues, lookat:=xlWhole) j = c.Column endRow = .UsedRange.Rows.Count endCol = .Cells(1, Columns.Count).End(xlToLeft).Column Range(.Cells(2, "B"), .Cells(endRow, endCol)).Copy wS1.Cells(2, j) End With Next k For i = 3 To wS1.UsedRange.Rows.Count For j = 1 To wS1.Cells(1, Columns.Count).End(xlToLeft).Column If wS1.Cells(i, j) <> "" And wS1.Cells(i, j) <> "→" And wS1.Cells(i, j) <> "退" Then With wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) .Value = wS1.Cells(i, j) .Offset(, 1) = wS1.Cells(1, j) k = j Do Until wS1.Cells(i, k) = "退" k = k + 1 Loop .Offset(, 2) = wS1.Cells(1, k) End With j = k End If Next j Next i wS2.Range("A1").CurrentRegion.Sort key1:=wS2.Range("B1"), order1:=xlAscending, Header:=xlYes wS2.Columns.AutoFit End Sub 'この行まで ※ 尚、保存時にはファイルの種類を「Excelマクロ有効ブック」で保存してください。 何度も失礼しました。m(_ _)m

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.5

No.1~3です。 補足を読みました。 結局 名簿Bookには各月1Sheetで12Sheetあり、当然のコトながら月跨ぎでの宿泊もある! というコトですね! いずれにしても1年分を1Sheetにまとめた方が処理が簡単だと思います。 関数で!というとかなり厄介になりますので、VBAでやってみました。 ただし、下準備として ↓の画像で左側が「名簿」Bookの各Sheetのレイアウトになります。 Sheet見出し上には4月~翌年の3月までの12Sheetが存在するとしています。 「4月」のSheet見出しをクリック → Shiftキーを押しながら最後の3月のSheet見出しをクリック! これで12Sheetが作業グループ化されましたので A1セルを選択 → 右クリック → セルの書式設定 → 表示形式 → ユーザー定義から 0年 と入力 → OK A2セルを選択 → 右クリック → セルの書式設定 → 表示形式 → ユーザー定義から 0月度 と入力 → OK B1セル → セルの表示形式はユーザー定義から d としておき、 =IF(MONTH(DATE($A1,$A2,COLUMN(A1)))=$A2,DATE($A1,$A2,COLUMN(A1)),"") という数式を入れます。 B2セルの数式は =IF(B1="","",TEXT(B1,"aaa")) として、B1・B2セルを範囲指定 → B2セルのフィルハンドルで31日分のAF列までコピー! → Sheet見出し上で右クリック → 作業グループ化を解除 各SheetのA1・A2セルに「年」と「月」の数値のみを入力していきます。 これで第一段階の準備は完了です。 この「名簿」Bookの13Sheet目を追加して Sheet名を「作業用」としておきます。 VBAでこの「作業用」Sheetに1年分のデータを表示させ、 そのデータを利用し、↓の画面右側の「宿泊一覧」BookのSheet1に表示させます。 「宿泊一覧」のSheet1のD2セルに =IF(A2="","",C2-B2+1) E2セルに =IF(A2="","",C2-B2) という数式を入れ両列ともオートフィルでしっかり下へコピーしておいてください。 これで下準備は完了です。 最後に「名簿」Bookを開き → Alt+F11キー → メニュー → 挿入 → 標準モジュールに ↓のコードをコピー&ペーストしマクロを実行してみてください。 (Alt+F8キー → マクロ → マクロ実行です) Sub 名簿更新() 'この行から Dim i As Long, j As Long, k As Long, endRow As Long, endCol As Long Dim c As Range, wS1 As Worksheet, wS2 As Worksheet Application.DisplayAlerts = False Workbooks.Open ("宿泊一覧") Application.DisplayAlerts = True Workbooks("名簿").Activate Set wS1 = Worksheets("作業用") Set wS2 = Workbooks("宿泊一覧").Worksheets("Sheet1") endRow = wS2.Cells(Rows.Count, "A").End(xlUp).Row If endRow > 1 Then Range(wS2.Cells(2, "A"), wS2.Cells(endRow, "C")).ClearContents End If endRow = wS1.UsedRange.Rows.Count If endRow > 1 Then wS1.Rows(2 & ":" & endRow).ClearContents End If For k = 1 To 12 With Worksheets(k) Set c = wS1.Rows(1).Find(what:=.Cells(1, "B"), LookIn:=xlValues, lookat:=xlWhole) j = c.Column endRow = .UsedRange.Rows.Count endCol = .Cells(1, Columns.Count).End(xlToLeft).Column Range(.Cells(2, "B"), .Cells(endRow, endCol)).Copy wS1.Cells(2, j) End With Next k For i = 3 To wS1.UsedRange.Rows.Count For j = 1 To wS1.Cells(1, Columns.Count).End(xlToLeft).Column If wS1.Cells(i, j) <> "" And wS1.Cells(i, j) <> "→" And wS1.Cells(i, j) <> "退" Then With wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) .Value = wS1.Cells(i, j) .Offset(, 1) = wS1.Cells(1, j) k = j Do Until wS1.Cells(i, k) = "退" k = k + 1 Loop .Offset(, 2) = wS1.Cells(1, k) End With j = k End If Next j Next i wS2.Range("A1").CurrentRegion.Sort key1:=wS2.Range("B1"), order1:=xlAscending, Header:=xlYes wS2.Columns.AutoFit End Sub 'この行まで ※ 今回も顧客名に重複はない!という前提です。 ※ 画像で、「田中」さんは月跨ぎにしてみました。 ※ 名簿シートの入力方法は画像のように最初に「お客様名」途中は「→」最後は「退」とします。 関数でないのでデータ変更があるたびにマクロを実行する必要があります。 この程度が今の段階では精一杯です。m(_ _)m

全文を見る
すると、全ての回答が全文表示されます。
  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.4

関数でやるにしてもVBAでやるにしても、月跨ぎ年跨ぎの場合がどうなっていてどの様にしたいのか解らないとなぁ……。

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.3

続けてお邪魔します。 名簿ファイルの作業用Sheet2の数式を前回の数式に変更すると 表示したいC列の数式も変わってしまいます。 C2セルの数式を =IFERROR(INDEX([名簿.xlsx]Sheet1!$A$1:$OJ$1,,SUMPRODUCT(([名簿.xlsx]Sheet2!$A$1:$OJ$300=A2)*COLUMN($A$1:$OJ$1))),"") に変更してください。 他の列の数式はそのままで大丈夫だと思います。 何度も失礼しました。m(_ _)m

sampei
質問者

補足

沢山書いていただいてありがとうございます! 表の矢印は入れておきたいのですが、その場合にはまた関数が変わってくるのでしょうか? 4月から3月までタブがあり、例えば5月のタブを押すと5月以降の表が表示されます。前月からの方は1日の欄に田中様なら(田中様)等とと表示しています。 出来れば月またぎの方の日数も計算できるようにしたいです。

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.2

No.1です! たびたびごめんなさい。 前回の数式では「→」に対処できていませんので、 元データに「→」は入力しないで作業用Sheet2のB3セルの数式を↓に変更してください。 =IF(Sheet1!B3="","",IF(Sheet1!B3="退",INDEX(Sheet1!$A3:A3,,MAX(IF(Sheet1!$A3:A3<>"",COLUMN($A$3:A3)))),COLUMN()*1000+ROW())) 前回同様、配列数式です。 ※ どうしても「→」を入力したい場合は別途数式を考える必要があります。 検証せずに投稿してごめんなさいね。m(_ _)m

sampei
質問者

お礼

三件の回答ありがとうございます! 補足は三件目にまとめて書かせていただきました。

全文を見る
すると、全ての回答が全文表示されます。
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.1

こんばんは! 関数での方法をご希望だというコトですので・・・ 一例です。 名簿.xlsx のSheet2を作業用のSheetとして使用します。 尚、元データはSheet1にあり、名前の重複はない!という前提です。 日付はシリアル値とします。 1年分のデータというコトですので、400列(OJ列)まで、行は300行までの数式としています。 名簿.xlsx のSheet2のB3セルに =IF(Sheet1!B3="","",IF(Sheet1!B3="退",INDEX(Sheet1!$A3:A3,,MAX(IF(Sheet1!$A3:A3<>"",IF(Sheet1!$A3:A3<>"→",COLUMN($A$3:A3)))))&"_"&Sheet1!B3,COLUMN()*1000+ROW())) これは配列数式になってしまいますので、Shift+Ctrl+Enterで確定! この画面からコピー&ペーストする場合は、上記数式をドラッグ&コピー → Sheet2のB3セルを選択 → 数式バー内に貼り付け → そのまま(編集可能なまま)Shift+Ctrlキーを押しながらEnterキーで確定! 数式の前後に{ }マークが入り配列数式になります。 これをOJ列まで、300行までコピーしておきます。 そして表示したいファイルのA2セルに =IFERROR(INDEX([名簿.xlsx]Sheet1!$A$1:OJJ$300,MOD(SMALL([名簿.xlsx]Sheet2!$A$1:$OJ$300,ROW(A1)),1000),INT(SMALL([名簿.xlsx]Sheet2!$A$1:$OJ$300,ROW(A1))/1000)),"") B2セルに =IFERROR(INDEX([名簿.xlsx]Sheet1!$A$1:$OJ$1,,SUMPRODUCT(([名簿.xlsx]Sheet1!$A$1:$OJ$300=A2)*COLUMN($A$1:$OJ$1))),"") C2セルに =IF(A2="","",INDEX([名簿.xlsx]Sheet1!$A$1:$OJ$1,,SUMPRODUCT(([名簿.xlsx]Sheet2!$A$1:$OJ$300=A2&"_"&"退")*COLUMN($A$1:$OJ$1)))) D2セルに =IF(A2="","",C2-B2+1) E2セルに =IF(A2="","",C2-B2) A2~E2セルを範囲指定 → E2セルのフィルハンドルで下へコピー! これで何とかご希望に近い形にならないでしょうか? ※ セルの表示形式は各列日付なり、○日 としてみてください。m(_ _)m

sampei
質問者

お礼

回答ありがとうございます! 補足は三件目にまとめて書かせていただきました。 私には少し難しいようですが、試してみます。 ありがとうございます!

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 一列から複数の範囲の値を抜き出す方法。

    エクセルを使用し、画像の左側のような表を作っています。説明の為、短くしてありますが実際のファイルは横にずらーっと日付が並んでおり、一年で一つのファイルです。 部屋番号も下に10ほど並んでおります。 画像を一枚に収めるために、表を二つ入れてありますが、実際にはこの二つの表は別々のファイルにしたいです。(左側の表のファイル名を名簿.xlsxlとします) 名簿.xlsxを別のエクセルファイル(宿泊一覧.xlsx)から読み込んで、 名簿.xlsxから宿泊者名を自動で抜き出して、滞在日数や泊数を計算させて表を作成させることは可能でしょうか? 画像を一枚に収めるために、表を二つ入れてありますが、実際にはこの二つの表は別々のファイルにしたいです。 名簿.xslxをどんどん更新すると、宿泊一覧にも名前が更新されるようにしたいのですが、関数だけではできないものなんでしょうか? VBAはよくわからないので、できれば関数でやるやり方を教えて頂ければありがたいです。

  • Excel:数式のブック名部分を関数にしたい

    今エクセル作業ですごく悩んでいることがあります。 色々調べたのですが、エラーになってしまうので、関数等に詳しい方に質問があります。 作業中のエクセル画面を簡単に再現した画像を添付するので、それを参照していただきたいのですが、 Dドライブの「資料フォルダ」に  2009.11東京一覧表 2009.11神奈川一覧表  2009.10東京一覧表 2009.10神奈川一覧表  2009.9東京一覧表 2009.9神奈川一覧表 などというエクセルファイルが沢山あるとします。 (ファイル名にピリオドを入れない方がいいのは存じていますので今回は気にしないでください) そして、現在作成中のエクセルの、B3にフォルダ内のエクセルブック名の年月の部分、C3に店舗名部分を入れると、C6にそのブック名の一覧表の「名簿」シートのB8セルの値が表示されるようになる、関数をお伺いしたいのです。 例えば、B3に「2009.11」C3に「東京」と入れると、C6に「2009.11東京一覧表」ブックの「名簿」シートのB8セルの値が出る・・・という感じです。 分からないながらに、自分でブック名の中に関数(セル番地?)を入れて   ='D:\資料フォルダ\[B3&C3&"一覧表.xls"]名簿'!$B$8 などと入力してみたのですが、[ ]の部分に関数(セル番地?)を入れると、エラーになってしまいました。 色々調べてINDIRECT関数というものを使ってみたりしたのですが、全くうまくいきません。 どうすれば希望通りに値が出るようになるか、お分かりの方は知恵をお貸しください。 どうかよろしくお願いします。

  • エクセルでセル参照元のファイル名に*を使いたい

    お世話になります。 別ファイルのエクセルシートの特定のセルを参照させたいのですが、下記のようにファイル名の後にワイルドカードを使う方法はないのでしょうか? =[HH一覧表.xlsx]Sheet1!$B$5 ⇒ =[HH一覧表*.xlsx]Sheet1!$B$5 「HH一覧表 1月・・・」というようにファイル名がHH一覧表から始まる複数のファイルが有って、そのファイルを開いた時に別のエクセルに指定のセルを参照させたいのですが、何か方法は無いでしょうか? VBAのコードは教えてもらったのですが、ハードルが高く簡便法を探しています。

  • エクセルで複数の条件を満たした値を返す関数を教えてください。

    エクセルで複数の条件を満たした値を返す関数を教えてください。 (画像を添付しました) 左の表(A1からD9)のデータを右の表でIDと製品を選択すると 会社名、名前が抽出するような関数を教えてください。 INDEXやMATCHなど使ってみたんですが、組み方が悪いのかうまく抽出できませんでした。 よろしくお願いします。

  • ハイパーリンクを自動で貼る

    本.xlsxというエクセルファイルのB列に データが並んでいるのですが、 本一覧.xlsxというエクセルファイルで 本.xlsxのB1の値で検索をかけて、見つかった そのセルナンバーを覚えて、本.xlsxのA1に こんな感じで [本一覧.xlsx]本一覧!c1835 ハイパーリンクをつけていっているのですが、 数がかなりあり、手動ではとても時間がかかってしまいます。 これをやることができる関数があれば教えてください。 他にマクロなど別の方法があればそちらでもかまいませんので、 よろしくお願いします。

  • エクセルで強制終了後の修復データが値の更新が出る

    エクセルで強制終了になり修復データを開きました。 すると関数の参照がおかしく正しく反映がされません。 ●正しい参照  '[商品情報 一覧表.xlsx]ピックアップ'!G8 ●修復後の参照  'C:\Users\master\AppData\Roaming\Microsoft\Excel\[商品情報 一覧表.xlsx]ピックアップ'!G8 C:\Users\master\AppData\Roaming\Microsoft\Excel に商品情報 一覧表のデータを置き開くと 正しい参照になりますが閉じると元に戻ります。 C:\Users\master\AppData\Roaming\Microsoft\Excel の文字を消しても消えません。 元に戻す方法はないでしょうか?

  • [EXCEL]外部エクセルの値の参照

    複数のエクセルファイルがあり、それぞれパスやファイル名が異なります。それぞれのファイルのパスの一覧の情報値を元に、各ファイルの指定セルを取得する関数はないでしょうか? indirect関数を用いた場合、そのファイルを開いておかなければならい欠点があるため、良い方法があればアドバイスを頂ければと思います。

  • VLOOKUP関数で得られた値「#N/A」は「0」にならないでしょうか?

     エクセル2000でVLOOKUP関数のことで教えてください。  利用日6桁、室名を2桁、時間帯を1桁、計9桁の検索値を持った施設利用状況一覧表をつくります。そして、この表をもとに毎日の利用一覧表もつくれるファイルづくりを考えています。  さて、この施設利用状況一覧表には飛番号が多く、VLOOKUP関数で検索をかけた場合、飛番号分には「#N/A」が返ってくることがわかったのですが、これを「0」(数として認識して欲しい)にする方法がないでしょうか。宜しくご教示の程お願いします。

  • 【Access2013】 上書き保存と追加保存

    会社PCがWin10&Office2013へ交換されました。 Excelファイル(xlsx)で出力する際、保存場所とファイル名を自由に指定できるようにしたく添付画像のようなコードを作成しました。 しかし、同名ファイルがあっても「上書き保存しますか?」ダイアログが出ない上に、違うテーブルやクエリーをExcel出力すると1つのxlsxファイル内に別sheetで保存されます。 (例) Q_管理表というクエリーを管理表.xlsxという名前で出力    →続けてテーブル1というテーブルをExcel出力し管理表.xlsxに上書き保存すると管理表.xlsxの中に「Q_管理表」「テーブル1」という2つのsheetで保存される    →続けてQ_管理表を再度出力するとsheet「テーブル1」はそのままでsheet「Q_管理表」は上書きされる 1つのxlsxファイル内に別sheetで保存されるのはむしろ好都合なので、上書き保存と追加保存を選択できるようなコードはありませんか? できない場合は「上書き保存しますか?」ダイアログを出して上書き保存させたいです。

  • エクセルでの外部データの取り込み?参照??

    いつもお世話になっております。 エクセル2007での外部データでの取り込みについてお尋ねします。 (条件:例) Aファイル(東京都xlsx 埼玉県xlsx 神奈川県xlsx・・・・・と複数ファイル(A列に日付、B列以降に気温、降水量・・・)) Bファイル(データファイル(随時更新):地域ごとの気温の一覧表(A列に日付、B列以降に気温))     と二種類のエクセルファイルがあります。 現在はAファイルごとにVLOOKUP関数によって、VLOOKUP(日付、外部データ、MATCH("東京都"・・・)みたいな関数で読み込んでおり、気温のグラフなんかを作成しています。 ここで質問です。 今後Aファイルの数を増やしていく予定で、上記のような方法ではデータを移動させた時にリンクがおかしくなってしまうのではないか??って不安で・・・このような操作を行う場合の最良の方法を教えてください。 どうぞよろしくお願いいたします。

専門家に質問してみよう