トップ回答者
VB 2010 によるエクセルの操作 図(図形)のグループ化、グループの解除の方法

質問
回答
-
完全分解とグループ化も含めて書いてみる
Imports Microsoft.Office.Interop.Excel Module Module1 Sub Main() Dim xla As Microsoft.Office.Interop.Excel.Application Dim xlbs As Workbooks Dim xlb As Workbook xla = New Microsoft.Office.Interop.Excel.Application() xla.Visible = True xlbs = xla.Workbooks xlb = xlbs.Open("D:\Book1.xlsx") 'ActiveSheetはWorkSheetではない場合がある If (TypeOf xlb.ActiveSheet Is Microsoft.Office.Interop.Excel.Chart) Then MsgBox("ActiveSheetはグラフになっています") ElseIf (TypeOf xlb.ActiveSheet Is Worksheet) Then Dim xlws As Worksheet xlws = xlb.ActiveSheet '分解 Dim shp As Shape For Each shp In xlws.Shapes If True Then 'グルーブの子要素をさらに分解する場合 UngroupAll(shp) Else '最上位のグループのみ分解する場合 shp.Ungroup() End If Next 'グループ化() Dim shapeNames As New List(Of Object) Dim shapes As Microsoft.Office.Interop.Excel.ShapeRange For i As Integer = 1 To xlws.Shapes.Count Step 2 'ためしに1個おきにグループ化してみる shp = xlws.Shapes.Item(i) shapeNames.Add(shp.Name) Next Dim o As Object() = shapeNames.ToArray() 'Listのままでは渡せないので配列に変換 shapes = xlws.Shapes.Range(o) shapes.Group() End If End Sub ''' <summary>グループ化されているShapeを完全分解する</summary> Public Sub UngroupAll(ByVal shp As Microsoft.Office.Interop.Excel.Shape) If (shp.Type = Microsoft.Office.Core.MsoShapeType.msoGroup) Then Dim allShapes As New List(Of Shape) Dim newShapes = New List(Of Shape) '分解前に存在するすべてのShapeを取得 For Each shpChild As Shape In CType(shp.Parent, Worksheet).Shapes If (shpChild.Name <> shp.Name) Then allShapes.Add(shpChild) End If Next shp.Ungroup() '分解後に存在するすべてのShapeを取得 For Each shpChild As Shape In CType(shp.Parent, Worksheet).Shapes newShapes.Add(shpChild) Next '差を見て分解して出てきたShapeを取り出す newShapes = newShapes.Except(allShapes).ToList() 'さらに分解 For Each shpChild In newShapes UngroupAll(shpChild) Next End If End Sub End Module
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 星 睦美 2016年9月30日 7:37
-
https://msdn.microsoft.com/ja-jp/library/office/ff860759.aspx
MsoShapeType.msoGroup は数値の 6 で定義されていますので、
For Each shp In sheet.Shapes If shp.Type = 6 Then 'Microsoft.Office.Core.MsoShapeType.msoGroup shp.Ungroup() 'グループ解除 End If Next shp
- 回答としてマーク 星 睦美 2016年9月30日 7:37
すべての返信
-
Excel 2013 & VB.NET 2010 で試しました。
Imports Microsoft.Office.Core Imports Microsoft.Office.Interop Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim app As Excel.Application Dim book As Excel.Workbook Dim sheet As Excel.Worksheet app = CreateObject("Excel.Application") app.Visible = False book = app.Workbooks.Open("C:\work\Book1.xlsx") sheet = book.Worksheets(1) For Each shp In sheet.Shapes If shp.Type = MsoShapeType.msoGroup Then shp.Ungroup() 'グループ解除 End If Next shp book.SaveAs("C:\work\Book2.xlsx") app.Quit() sheet = Nothing book = Nothing app = Nothing End Sub End Class
ほぼ同じようなコードで行けました。
- 編集済み kenjinoteMVP 2016年8月25日 9:49
-
完全分解とグループ化も含めて書いてみる
Imports Microsoft.Office.Interop.Excel Module Module1 Sub Main() Dim xla As Microsoft.Office.Interop.Excel.Application Dim xlbs As Workbooks Dim xlb As Workbook xla = New Microsoft.Office.Interop.Excel.Application() xla.Visible = True xlbs = xla.Workbooks xlb = xlbs.Open("D:\Book1.xlsx") 'ActiveSheetはWorkSheetではない場合がある If (TypeOf xlb.ActiveSheet Is Microsoft.Office.Interop.Excel.Chart) Then MsgBox("ActiveSheetはグラフになっています") ElseIf (TypeOf xlb.ActiveSheet Is Worksheet) Then Dim xlws As Worksheet xlws = xlb.ActiveSheet '分解 Dim shp As Shape For Each shp In xlws.Shapes If True Then 'グルーブの子要素をさらに分解する場合 UngroupAll(shp) Else '最上位のグループのみ分解する場合 shp.Ungroup() End If Next 'グループ化() Dim shapeNames As New List(Of Object) Dim shapes As Microsoft.Office.Interop.Excel.ShapeRange For i As Integer = 1 To xlws.Shapes.Count Step 2 'ためしに1個おきにグループ化してみる shp = xlws.Shapes.Item(i) shapeNames.Add(shp.Name) Next Dim o As Object() = shapeNames.ToArray() 'Listのままでは渡せないので配列に変換 shapes = xlws.Shapes.Range(o) shapes.Group() End If End Sub ''' <summary>グループ化されているShapeを完全分解する</summary> Public Sub UngroupAll(ByVal shp As Microsoft.Office.Interop.Excel.Shape) If (shp.Type = Microsoft.Office.Core.MsoShapeType.msoGroup) Then Dim allShapes As New List(Of Shape) Dim newShapes = New List(Of Shape) '分解前に存在するすべてのShapeを取得 For Each shpChild As Shape In CType(shp.Parent, Worksheet).Shapes If (shpChild.Name <> shp.Name) Then allShapes.Add(shpChild) End If Next shp.Ungroup() '分解後に存在するすべてのShapeを取得 For Each shpChild As Shape In CType(shp.Parent, Worksheet).Shapes newShapes.Add(shpChild) Next '差を見て分解して出てきたShapeを取り出す newShapes = newShapes.Except(allShapes).ToList() 'さらに分解 For Each shpChild In newShapes UngroupAll(shpChild) Next End If End Sub End Module
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 星 睦美 2016年9月30日 7:37
-
ご回答ありがとうございました。
エクセルのバージョンに依存しないアプリの開発しております。
参照の追加をしない手法で、お願い致します。
最初に書いておけば良かったのですが、申し訳ございません。
Public Class Form1
Public Shared xlApp As Object, xlBook As Object, xlSheet As Object
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim MsoShapeType
xlApp = GetObject(, "Excel.Application")
xlBook = xlApp.activeworkbook
xlSheet = xlBook.ActiveSheet
For Each shp In xlSheet.Shapes
If shp.Type = MsoShapeType.msoGroup Then ← ここでエラーがでます。
shp.Ungroup()
End If
Next shpEnd Sub
End Class -
https://msdn.microsoft.com/ja-jp/library/office/ff860759.aspx
MsoShapeType.msoGroup は数値の 6 で定義されていますので、
For Each shp In sheet.Shapes If shp.Type = 6 Then 'Microsoft.Office.Core.MsoShapeType.msoGroup shp.Ungroup() 'グループ解除 End If Next shp
- 回答としてマーク 星 睦美 2016年9月30日 7:37