PasteTextFromMergedCellCopy|セル結合範囲を値だけのコピー&ペーストを可能にする|Excel VBA
- yuji fukami
- 30false16 GMT+0000 (Coordinated Universal Time)
- 読了時間: 8分
概要
今回紹介する汎用プロシージャ PasteTextFromMergedCellCopy は、セル結合を含む範囲をコピーしたときでも、貼り付け先へ「値だけ」を反映できるようにする Excel VBA マクロです。
Excelでは、結合セルを含む範囲に対して通常の「値だけ貼り付け」を行おうとすると、うまく貼り付けできなかったり、思った通りに処理できなかったりすることがあります。このマクロを使えば、貼り付け先のレイアウトや書式はそのままに、中身の値だけを反映することができます。
実際の動作(セル結合範囲のコピー&ペースト)
まずは動画を見ていただくと分かりやすいですが、今回紹介する汎用プロシージャは、セル結合を含む範囲に対して「値だけ貼り付け」を行えるようにするマクロです。
動画では、B3:N6 の範囲をコピーし、同じセル結合が施された B10:N13 の範囲へ値だけ貼り付けしようとしています。このようなケースで、Excel の標準機能だけで何とかしようとしても、うまく貼り付けできなかったり、エラーになってしまったりすることがあります。
今回の方法では、まず元のセル範囲をコピーした状態で、貼り付け先の左上となるセルを選択します。そのうえで、このマクロを登録したボタンを押して「結合範囲に値貼り付け」を実行すると、一発でセル値だけを貼り付けることができます。
実際に確認していただくと分かりますが、コピーされるのはあくまで値だけです。そのため、セルの色や塗りつぶし、書式などはコピーされず、貼り付け先のレイアウトをそのまま維持したまま中身だけを反映できます。
この処理が役立つ場面
帳票やレイアウト表では、見た目の都合でセル結合を使わざるを得ない場面があります。そのような表の内容を別の場所へそのままコピーしたいときでも、書式やセルの色、塗りつぶしまで一緒にコピーされるのは避けたい、値だけを反映したいというケースはよくあります。
ただ、これを標準機能だけで対応しようとすると、セルごとに内容をコピーして貼り付ける必要が出てきて、何度もシート間を行き来しなければならず、かなり手間がかかります。
このマクロを使えば、そうした面倒な作業をせずに、コピーしたセル範囲の内容を一度にまとめて値だけ貼り付けできるようになります。セル結合を含むレイアウトを崩さずに、中身だけを差し替えたいときに便利な処理です。
実装例
具体的な実装例としては、添付画像のように帳票の近くにこのマクロを登録したボタンを配置しておく方法が使いやすくておすすめです。
画像では簡単な例として、セル結合を含む入力用の帳票を用意し、その右上付近に「結合範囲に値貼付け」というボタンを配置しています。このボタンには、今回紹介している PasteTextFromMergedCellCopy マクロを登録しておきます。

このようにしておくと、別の帳票や一覧表などから内容をコピーしてきたときに、貼り付け先となるセルを選択して、そのまますぐにボタンを押すだけで処理を実行できます。つまり、マクロを毎回開発タブから探したり、ショートカットを別途覚えたりしなくても、現場で直感的に使える形にできるというわけです。
特に、帳票を繰り返し使う業務では、貼り付け位置を選んですぐに実行できる状態にしておくことで、作業がかなりスムーズになります。操作手順もシンプルなので、VBAに慣れていない人が使う場合でも分かりやすく、実務向きの実装方法といえます。
ソースコード
「PasteTextFromMergedCellCopy 」は下記の通りです。
本記事の最後には解説(AI作成)も載せておきます
PasteTextFromMergedCellCopy で使用している汎用プロシージャは別記事にて解説しています。
・GetClipText:https://www.softex-celware.com/post/getcliptext
・GetSelectionCell:https://www.softex-celware.com/post/getselectioncell
・OffsetCell:https://www.softex-celware.com/post/offsetcell
ソースコード解説
処理全体の流れ
まず、メイン処理は次の PasteTextFromMergedCellCopy です。
Public Sub PasteTextFromMergedCellCopy()このプロシージャでは、次の流れで処理を進めています。
クリップボードからコピー済みの文字列を取得する
取得した文字列を行・列の構造を持つ二次元配列に変換する
現在選択しているセルを貼り付け開始位置として取得する
配列の内容を1セルずつ順番に書き込む
つまり、見た目としては「値だけ貼り付け」ですが、内部的には貼り付け処理を自前で再現しているような構成になっています。
PasteTextFromMergedCellCopy の役割
メイン処理部分では、まずクリップボードの文字列を取得しています。
Dim Text As String: Text = GetClipTextIf Text = "" Then Exit Subコピー内容が取得できなければ、そのまま終了します。ここで取得しているのはセルそのものではなく、コピーされた範囲のテキスト表現です。
続いて、その文字列を二次元配列へ変換しています。
Dim Output As Variant: Output = ConvCellCopyTextToArray(Text)この Output は、「何行目・何列目にどの値を入れるか」を表した配列です。
その後、現在の選択セルを貼り付け開始位置として取得します。
Dim SelectCell As Range: Set SelectCell = GetSelectionCell
If SelectCell Is Nothing Then Exit Sub最後に、二重ループで配列の値を1セルずつ順番に書き込んでいます。
For I = 1 To N
For J = 1 To M
Set TmpCell = OffsetCell(SelectCell, I - 1, J - 1)
TmpText = Output(I, J)
If TmpCell.Value <> TmpText Then
TmpCell.Value = TmpText
End If
Next
Nextこのようにすることで、Excel の PasteSpecial を使わずに、貼り付け先へ値だけを順番に反映できます。
なお、
If TmpCell.Value <> TmpText Thenという判定を入れているため、同じ値であれば再代入しません。この一文によって、無駄な書き込みを減らし、少しでも高速に動作するよう配慮されています。
GetClipText でクリップボードから文字列を取得する
次の関数は、クリップボード内の文字列を取得するためのものです。
Public Function GetClipText() As String内部では DataObject を使っています。
Dim Clip As New DataObjectWith Clip .GetFromClipboard Output = .GetTextEnd Withこれにより、Excel でコピーしたセル範囲を文字列として取り出すことができます。
ここでのポイントは、セルの情報をそのまま持ち回っているのではなく、クリップボード上の文字列を解析して再配置しているという点です。
そのため、この仕組みは「貼り付け」そのものというより、コピー内容をいったんテキスト化して復元する処理に近い考え方になっています。
ConvCellCopyTextToArray が今回の中心処理
このマクロの中核になるのが、次の関数です。
Public Function ConvCellCopyTextToArray(Text As String) As VariantExcel でセル範囲をコピーすると、クリップボード上では
行の区切り:vbCrLf
列の区切り:Chr(9)(タブ)
という形で表現されます。
そこでこの関数では、まず末尾の改行を削除し、
If Right(Text, 2) = vbCrLf Then Text = Mid(Text, 1, Len(Text) - 2)End Ifそのあとで、改行ごとに行を分割し、さらに各行をタブで分割しています。
ListSplitCrLf = Split_Start1(Text, vbCrLf)TmpSplit = Split_Start1(StrSplitCrLf, Chr(9))これによって、コピーされた内容を行列構造を持つ配列として扱えるようになります。
また、セル内改行を含む値については、クリップボード上でダブルクォーテーションが付くことがあるため、次の処理で不要な " を取り除いています。
If InStr(TmpText, vbLf) > 0 Then TmpText = Replace(TmpText, """", "")End Ifこのあたりは実務上かなり重要で、単純に Split しただけでは崩れやすい部分を丁寧に補正しています。
Split_Start1 と ConvArray1D_Start1 の役割
今回のコードでは、文字列分割の補助として Split_Start1 を使っています。
Public Function Split_Start1(...)VBA 標準の Split 関数は、返ってくる配列が 0 始まりです。しかし今回のコードでは、ループを分かりやすくするために1始まり配列で統一しています。
そのため、
Split_Start1
ConvArray1D_Start1
の2つを使って、分割結果を扱いやすい形に整えています。
特に Split_Start1 は、区切り文字が存在しない場合でも1要素の配列として返してくれるため、後続処理が安定しやすいです。「毎回同じ前提で処理できるようにしている」という意味で、汎用部品としても使いやすい作りになっています。
GetSelectionCell で貼り付け開始位置を取得する
貼り付け先の基準位置を取得しているのが、次の関数です。
Public Function GetSelectionCell() As Range内部では Selection を確認し、それが Range である場合のみセルを返しています。
Dim Dummy As Object: Set Dummy = SelectionIf TypeName(Dummy) = "Range" Then Set Output = DummyEnd Ifこれにより、図形やグラフなどセル以外が選択されていた場合には Nothing を返せるため、不要なエラーを防ぐことができます。
OffsetCell で結合セルの影響を受けないセル参照を行う
今回の処理では、貼り付け先の各セルを順番に取得するために OffsetCell を使っています。
Public Function OffsetCell(ByRef Cell As Range, _
Optional ByRef RowOffset As Long = 0, _
Optional ByRef ColOffset As Long = 0) As Range通常であれば Range.Offset を使う方法もありますが、結合セルが絡むと感覚とずれることがあります。そこでこの関数では、対象シートの Cells(Row, Column) を直接使って、
Set Output = Sheet.Cells(Cell.Row + RowOffset, _ Cell.Column + ColOffset)という形で取得しています。
これにより、結合状態に引っ張られず、純粋に行番号・列番号ベースでセルを取得できるようになっています。今回のような「結合セルを含む範囲の値だけ貼り付け」では、かなり相性の良い作りです。
このコードのポイント
今回のコードの大きなポイントは、Excel の標準貼り付け機能をそのまま使うのではなく、コピー内容を文字列として取り出し、自前で表構造を復元して貼り付けていることです。
そのため、
書式は貼り付けない
色や塗りつぶしも貼り付けない
結合状態は貼り付け先のものをそのまま使う
値だけを反映する
という目的にとても合った処理になっています。
特に、帳票や入力フォームのように、貼り付け先のレイアウトは固定で、中身だけ差し替えたいという場面では非常に使いやすいです。
使用時の前提と注意点
このマクロはとても便利ですが、前提条件もあります。
まず、貼り付け先はコピー元と同じようなセル配置・結合構造であることが前提です。結合の仕方が大きく異なる場所へ貼り付ける用途には向いていません。
また、扱っているのはあくまで値なので、
数式そのもの
書式
罫線
背景色
コメント
入力規則
などは引き継がれません。
逆に言えば、こうしたものを維持したまま中身だけ差し替えたいときにこそ、このマクロの強みがあります。



