top of page

​タグ一覧

配列処理(73)

階層化フォーム(33)

ファイル操作(28)

開発事例(22)

シート・セル操作(20)

図形操作(15)

ユーザーフォーム(10)

コード自動生成(10)

設計思想(10)

講座実施報告(10)

文字列操作(8)

数学(7)

開発効率化(6)

GAS(5)

アニメーション(5)

技術解説(4)

イミディエイトウィンドウ(4)

Googleスプレッドシート(4)

副業(4)

クリップボード(4)

条件付き書式(4)

その他(4)

OneDrive(3)

イベントプロシージャ(3)

ココナラ(3)

小説(3)

HTML(3)

JavaScript(3)

Enum(2)

PDF(2)

フリーランス(2)

リスキリング(2)

Outlook(2)

介護(2)

Discord(2)

シフト表(2)

LookerStudio(2)

日報(2)

カレンダー(2)

罫線(2)

パズル(2)

小ネタ(2)

コード解説(2)

クラスモジュール(2)

Antigravity(2)

ステータスバー(1)

コード解析(1)

バックアップ(1)

可変長引数配列(1)

ブック処理(1)

スクレイピング(1)

スプレッドシート(1)

coconala(1)

リボン登録マクロ(1)

QRコード(1)

実行予約(1)

給与計算(1)

VBA不使用(1)

リボン(1)

超勉強会(1)

スピログラフ(1)

図名描写(1)

連想配列(1)

溶接ロボット(1)

保育士(1)

楽天市場(1)

経理(1)

医療(1)

文書作成(1)

発注書(1)

ショートカット(1)

WebAPI(1)

色操作(1)

スーパー開発ショートカット(1)

ライブラリ処理(1)

放課後等デイサービス(1)

児童福祉支援(1)

学校(1)

UI(1)

CAD(1)

カーソル操作(1)

チェックボックス(1)

Webアプリ(1)

PowerShell(1)

PasteTextFromMergedCellCopy|セル結合範囲を値だけのコピー&ペーストを可能にする|Excel VBA

  • 執筆者の写真: yuji fukami
    yuji fukami
  • 30false16 GMT+0000 (Coordinated Universal Time)
  • 読了時間: 8分

概要

今回紹介する汎用プロシージャ PasteTextFromMergedCellCopy は、セル結合を含む範囲をコピーしたときでも、貼り付け先へ「値だけ」を反映できるようにする Excel VBA マクロです。


Excelでは、結合セルを含む範囲に対して通常の「値だけ貼り付け」を行おうとすると、うまく貼り付けできなかったり、思った通りに処理できなかったりすることがあります。このマクロを使えば、貼り付け先のレイアウトや書式はそのままに、中身の値だけを反映することができます。

実際の動作(セル結合範囲のコピー&ペースト)

まずは動画を見ていただくと分かりやすいですが、今回紹介する汎用プロシージャは、セル結合を含む範囲に対して「値だけ貼り付け」を行えるようにするマクロです。




動画では、B3:N6 の範囲をコピーし、同じセル結合が施された B10:N13 の範囲へ値だけ貼り付けしようとしています。このようなケースで、Excel の標準機能だけで何とかしようとしても、うまく貼り付けできなかったり、エラーになってしまったりすることがあります。


今回の方法では、まず元のセル範囲をコピーした状態で、貼り付け先の左上となるセルを選択します。そのうえで、このマクロを登録したボタンを押して「結合範囲に値貼り付け」を実行すると、一発でセル値だけを貼り付けることができます。


実際に確認していただくと分かりますが、コピーされるのはあくまで値だけです。そのため、セルの色や塗りつぶし、書式などはコピーされず、貼り付け先のレイアウトをそのまま維持したまま中身だけを反映できます。


この処理が役立つ場面

帳票やレイアウト表では、見た目の都合でセル結合を使わざるを得ない場面があります。そのような表の内容を別の場所へそのままコピーしたいときでも、書式やセルの色、塗りつぶしまで一緒にコピーされるのは避けたい、値だけを反映したいというケースはよくあります。


ただ、これを標準機能だけで対応しようとすると、セルごとに内容をコピーして貼り付ける必要が出てきて、何度もシート間を行き来しなければならず、かなり手間がかかります。

このマクロを使えば、そうした面倒な作業をせずに、コピーしたセル範囲の内容を一度にまとめて値だけ貼り付けできるようになります。セル結合を含むレイアウトを崩さずに、中身だけを差し替えたいときに便利な処理です。


実装例

具体的な実装例としては、添付画像のように帳票の近くにこのマクロを登録したボタンを配置しておく方法が使いやすくておすすめです。


画像では簡単な例として、セル結合を含む入力用の帳票を用意し、その右上付近に「結合範囲に値貼付け」というボタンを配置しています。このボタンには、今回紹介している PasteTextFromMergedCellCopy マクロを登録しておきます。

Excelシートに青いセルが結合され強調。右上に「結合範囲に値貼付」、右下に「何かしら提票」と記載。マクロ案内もあり。

このようにしておくと、別の帳票や一覧表などから内容をコピーしてきたときに、貼り付け先となるセルを選択して、そのまますぐにボタンを押すだけで処理を実行できます。つまり、マクロを毎回開発タブから探したり、ショートカットを別途覚えたりしなくても、現場で直感的に使える形にできるというわけです。


特に、帳票を繰り返し使う業務では、貼り付け位置を選んですぐに実行できる状態にしておくことで、作業がかなりスムーズになります。操作手順もシンプルなので、VBAに慣れていない人が使う場合でも分かりやすく、実務向きの実装方法といえます。


ソースコード

PasteTextFromMergedCellCopy 」は下記の通りです。

本記事の最後には解説(AI作成)も載せておきます


PasteTextFromMergedCellCopy で使用している汎用プロシージャは別記事にて解説しています。



ソースコード解説

処理全体の流れ

まず、メイン処理は次の PasteTextFromMergedCellCopy です。

Public Sub PasteTextFromMergedCellCopy()

このプロシージャでは、次の流れで処理を進めています。

  1. クリップボードからコピー済みの文字列を取得する

  2. 取得した文字列を行・列の構造を持つ二次元配列に変換する

  3. 現在選択しているセルを貼り付け開始位置として取得する

  4. 配列の内容を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 Variant

Excel でセル範囲をコピーすると、クリップボード上では

  • 行の区切り: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 の標準貼り付け機能をそのまま使うのではなく、コピー内容を文字列として取り出し、自前で表構造を復元して貼り付けていることです。

そのため、

  • 書式は貼り付けない

  • 色や塗りつぶしも貼り付けない

  • 結合状態は貼り付け先のものをそのまま使う

  • 値だけを反映する

という目的にとても合った処理になっています。

特に、帳票や入力フォームのように、貼り付け先のレイアウトは固定で、中身だけ差し替えたいという場面では非常に使いやすいです。


使用時の前提と注意点

このマクロはとても便利ですが、前提条件もあります。

まず、貼り付け先はコピー元と同じようなセル配置・結合構造であることが前提です。結合の仕方が大きく異なる場所へ貼り付ける用途には向いていません。

また、扱っているのはあくまでなので、

  • 数式そのもの

  • 書式

  • 罫線

  • 背景色

  • コメント

  • 入力規則

などは引き継がれません。

逆に言えば、こうしたものを維持したまま中身だけ差し替えたいときにこそ、このマクロの強みがあります。


Excel VBAによる業務自動化・ツール開発をご検討の方へ

​"脱Excel"の前に、現状のExcelの潜在能力を120%発揮してみませんか?

Softex-Celware

​インボイス登録番号:T5810983887134

  • Facebook
  • Twitter
  • YouTube

©2023 softex-celware。Wix.com で作成されました。

bottom of page