Below code count pictures that are pasted (by other macro) as msorectangle shape in excel worksheet and position them in 1 row in specific distance beetween each of them. I need to add another restrctions to positioning and im struggling with coding it. Question is how to upgrade this code if:
If number of pictures is <=6 than 1 row of pictures and set size to h:7,25cm w:4,7cm
If number of pictures is >6 and <=11 then 1 row of pictures with size h:5,9cm w:3,8cm
If number of pictures is =12 than 2 rows with size from 1 point h:7,25cm w:4,7cm.
If number of pictures is >12 than every (7, 13, 19, 25 etc. pic) is starting from next row with size from point nr 2 h:5,9cm w:3,8cm
The list of pictures is dynamic.
Sub Sample2()
Dim shp As Shape, shp2 As Shape
Dim ws As Worksheet
Dim lstShp As Integer
Dim shpLft As Double, shpTop As Double, shpWidth As Double, shpHeight As Double
Dim inBetweenMargin As Double
Dim i As Long
'~~> In betwen margin
inBetweenMargin = 8
Set ws = ThisWorkbook.Worksheets("wk")
With ws
'~~> Get the max shape number(name)
For Each shp In .Shapes
If shp.AutoShapeType = msoShapeRectangle Then
If Val(shp.Name) > 1 And Val(shp.Name) > lstShp Then _
lstShp = Val(shp.Name)
End If
Next
'~~> Loop through the shapes
For i = 1 To lstShp
'~~> This is required in case you delete shape 3
'~~> and have only shapes 1,2,4,5 etc...
On Error Resume Next
Set shp = .Shapes(CStr(i))
'shp2 = first photo
Set shp2 = ws.Shapes("1")
On Error GoTo 0
'~~> position them
If Not shp Is Nothing And shp.AutoShapeType = msoShapeRectangle Then
If shpLft = 0 And shpTop = 0 And shpWidth = 0 Then
shpLft = shp.Left
shpTop = shp.Top
shpWidth = shp.Width
Else
shp.Top = shpTop
shp.Left = shpLft + shpWidth + inBetweenMargin
shpLft = shp.Left
shpWidth = shp.Width
End If
End If
'position picture nr 7 and above in second row
If Val(shp.Name) = 7 Then
shp.Top = shp2.Top + shp2.Height + inBetweenMargin
shp.Left = shp2.Left
shpLft = shp.Left
shpWidth = shp.Width
End If
If Val(shp.Name) >= 8 Then
shp.Top = shp2.Top + shp2.Height + inBetweenMargin
End If
Next i
End With
End Sub
For the 2nd last condition, if the total picture count is 12 then I am safely assuming that you need 6 per line. And for the last condition you want 7 per line. For these two we will use a Counter and then we will do either Counter Mod 6 or Counter Mod 7 for that purpose. You can read about Mod operator in MS KB.
The logic is to reset the .Top and .Left in the next line for the last 2 conditions.We will use a boolean variable for that.
Is this what you are trying?
Option Explicit
Sub Sample()
Dim shp As Shape, shp2 As Shape
Dim ws As Worksheet
Dim lstShp As Integer
Dim shpLft As Single, shpTop As Single, shpWidth As Single, shpHeight As Single
Dim oldLeft As Single, oldTop As Single
Dim inBetweenMargin As Single
Dim i As Long, counter As Long, picCount As Long
Dim nextLine As Boolean, MultipleRows As Boolean
Dim ModByNumber As Long
'~~> In betwen margin
inBetweenMargin = 8
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws
'~~> Get the max shape number(name)
For Each shp In .Shapes
If shp.AutoShapeType = msoShapeRectangle Then
If Val(shp.Name) > 1 And Val(shp.Name) > lstShp Then _
lstShp = Val(shp.Name)
picCount = picCount + 1
End If
Next
Select Case picCount
Case 1 To 6
'~~> Set your default height and Width
shpHeight = 7.25 * 28.34646 '<~~ Cm to Points
shpWidth = 4.7 * 28.34646 '<~~ Cm to Points
Case 7 To 11
'~~> Set your default height and Width
shpHeight = 5.9 * 28.34646 '<~~ Cm to Points
shpWidth = 3.8 * 28.34646 '<~~ Cm to Points
Case 12
'~~> Set your default height and Width
shpHeight = 7.25 * 28.34646 '<~~ Cm to Points
shpWidth = 4.7 * 28.34646 '<~~ Cm to Points
MultipleRows = True
ModByNumber = 6
Case Is > 12
'~~> Set your default height and Width
shpHeight = 5.9 * 28.34646 '<~~ Cm to Points
shpWidth = 3.8 * 28.34646 '<~~ Cm to Points
MultipleRows = True
ModByNumber = 7
End Select
nextLine = False
'~~> Loop through the shapes
For i = 1 To lstShp
'~~> This is required in case you delete shape 3
'~~> and have only shapes 1,2,4,5 etc...
On Error Resume Next
Set shp = .Shapes(CStr(i))
On Error GoTo 0
'~~> position them
If Not shp Is Nothing Then
If shp.AutoShapeType = msoShapeRectangle Then
If shpLft = 0 And shpTop = 0 Then
shpLft = shp.Left
shpTop = shp.Top
shp.Height = shpHeight
shp.Width = shpWidth
'~~> Storing the top and left for resetting
'~~> when moving to next line
oldTop = shp.Top
oldLeft = shp.Left
counter = counter + 1
Else
shp.Top = shpTop
oldTop = shpTop
If nextLine = True Then
shp.Left = shpLft
nextLine = False
counter = 1
Else
shp.Left = shpLft + shpWidth + inBetweenMargin
counter = counter + 1
End If
shp.Height = shpHeight
shp.Width = shpWidth
shpLft = shp.Left
If MultipleRows = True Then
If counter Mod ModByNumber = 0 Then
shpLft = oldLeft
shpTop = oldTop + shpHeight + inBetweenMargin
nextLine = True
End If
End If
End If
End If
End If
'~~> This is required if there is no shape between 4 and 6.
'~~> 5 gets deleted? Also the reason why we are not using "i Mod 7"
'~~> and using "counter Mod 7"
Set shp = Nothing
Next i
End With
End Sub
Screenshots
If number of pictures is 6 than 1 row and set size to h:7,25cm w:4,7cm
If number of pictures is >7 and <=10 then 1 row of pictures with size h:5,9cm w:3,8cm
If number of pictures is <12 than 2 rows with size from 1 point.
If number of pictures is >12 than every 7 pic is starting from next row with size from point nr 2
So if we take i as the amount of pictures:
We can do some simple calculations to check which condition is met and use Select Case
to identify and assign each of your 4 cases like so:
Select Case i
Case IS >= 12
numberofrows = i \ 7 '(this only gives whole numbers)
Formatting = 2
Case IS > 10
numberofrows = 2
Formatting = 1
Case IS >= 7
numberofrows = 1
Formatting = 2
Case ELSE
numberofrows = 1
Formatting = 1
End Select
Related
I'm relatively new to VBA.
I'm helping an internal team to improve workflow by reducing errors when copying and pasting data from Excel to PowerPoint.
How do I configure conditional formatting in the PowerPoint table based on two rules?
2-Color Scale:
Icon Set:
My current code is as follows. This has allowed for data to be copied from a single Excel cell to a single PowerPoint table cell.
Sub TableData()
Dim oPPApp As Object, oPPrsn As Object, oPPSlide As Object
Dim oPPShape As Object
Dim FlName As String
FlName = "FILE PATH"
On Error Resume Next
Set oPPApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set oPPApp = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
oPPApp.Visible = True
Set oPPrsn = oPPApp.Presentations.Open(FlName)
Set oPPSlide = oPPrsn.Slides(1)
Set oPPShape = oPPSlide.Shapes(2)
ThisWorkbook.Sheets("Sheet1").Activate
oPPShape.Table.Cell(2, 3).Shape.TextFrame.TextRange.Text = Range("C1").Value
End Sub
For the table creation, the code is based on this answer I received, so you may have to adjust the code to your liking (it creates a slide for each row), the dimensions of the source and target table are based on my needs, since your code works only for one cell I wanted to test with more data.
The relevant part for your request is anyway this one:
Dim RGB_Val As String
RGB_Val = rng(i).DisplayFormat.Interior.Color
newTable.cell(i, 2).Shape.Fill.ForeColor.RGB = RGB_Val
that takes the background color of Conditionally Formatted cells (so you would have to apply conditional formatting to the Excel table, first) (information gathered from this answer and this one taking care of the comment Jun 9, 2018 at 13:08).
In each slide created following the row, each Excel column cell will then become a row in PPT, on the second column, while on the first there will be the circles, whose size can be defined by FlowRatio's value.
Their colors will have to be defined as per below (values and colors taken from your screenshot):
If rng(i).Value >= 12 Then
ElseIf rng(i).Value < 12 And rng(i).Value >= -12 Then
ElseIf rng(i).Value < -12 Then
So, from this:
you will get this:
but as per above, you may have to adjust sizes of the ranges to avoid errors.
Ah, it runs from Excel to PPT.
Sub CopyConditionalFormattingAddChecks()
Dim DataRange As Range, DataRow As Range, rng As Range, i As Long, col As Long
Dim ppApp As PowerPoint.Application, pres As PowerPoint.Presentation
Dim sld As PowerPoint.slide, newTable As PowerPoint.Table, Sldss As Slides
Dim CellLeft As Single
Dim CellTop As Single
Dim CellWidth As Single
Dim CellHeight As Single
Dim CellWidth_2 As Single
Dim Shp_Cntr As Single
Dim Shp_Mid As Single
Dim CircleCheck As PowerPoint.Shape
Dim IconNavigator As Object
Dim RGB_Val As String
Dim SlideCounter As Integer
Dim FlowCounter As Integer
Dim IconCounter As Integer
Dim TestCounter As Integer
FlowRatio = 0.6
On Error Resume Next
Set ppApp = GetObject(, "PowerPoint.Application")
Set pres = ppApp.ActivePresentation
On Error GoTo 0
If pres Is Nothing Then
MsgBox "Destination presentation must be open in PowerPoint", vbCritical
Exit Sub
End If
SlideCounter = 0
CircleCheckCounter = 0
Set DataRange = Selection
For Each DataRow In DataRange.Rows
Set sld = pres.Slides.AddSlide(pres.Slides.Count + 1, pres.SlideMaster.CustomLayouts(2))
SlideCounter = SlideCounter + 1
Set newTable = sld.Shapes.AddTable(14, 4).Table ' different here
With newTable.Columns(1): .Width = 5: End With
With newTable.Columns(2): .Width = 60: End With
With newTable.Columns(3): .Width = 5: End With
With newTable.Columns(4): .Width = 50: End With
With sld.Shapes.Placeholders(2): .Width = 550: End With
Set rng = DataRow.Cells(1).Resize(1, 10)
For i = 1 To newTable.Rows.Count
newTable.cell(i, 2).Shape.TextFrame2.TextRange.Text = rng.Cells(i).Value
RGB_Val = rng(i).DisplayFormat.Interior.Color
newTable.cell(i, 2).Shape.Fill.ForeColor.RGB = RGB_Val
If rng(i).Value >= 12 Then
CellTop = newTable.cell(i, 1).Shape.Top
CellLeft = newTable.cell(i, 1).Shape.Left
CellWidth = newTable.cell(i, 1).Shape.Width
CellHeight = newTable.cell(i, 1).Shape.Height
Shp_Cntr = CellLeft + CellWidth / 2
Shp_Mid = CellTop + CellHeight / 2
Set CircleCheck = sld.Shapes.AddShape(Type:=msoShapeOval, Left:=Shp_Cntr - (CellHeight * FlowRatio / 2), Top:=Shp_Mid - (CellHeight * FlowRatio / 2), Width:=CellHeight * FlowRatio, Height:=CellHeight * FlowRatio)
CircleCheck.Fill.ForeColor.RGB = RGB(214, 85, 50)
CircleCheck.Line.Weight = 0.75
CircleCheck.Line.ForeColor.RGB = RGB(255, 255, 255)
CircleCheck.Line.Visible = msoTrue
CircleCheck.LockAspectRatio = msoTrue
CircleCheck.Name = "CircleCheck " & CircleCheckCounter
CircleCheck.ZOrder msoBringToFront
ElseIf rng(i).Value < 12 And rng(i).Value >= -12 Then
CellTop = newTable.cell(i, 1).Shape.Top:
CellLeft = newTable.cell(i, 1).Shape.Left
CellWidth = newTable.cell(i, 1).Shape.Width
CellHeight = newTable.cell(i, 1).Shape.Height
Shp_Cntr = CellLeft + CellWidth / 2
Shp_Mid = CellTop + CellHeight / 2
'
Set CircleCheck = sld.Shapes.AddShape(Type:=msoShapeOval, Left:=Shp_Cntr - (CellHeight * FlowRatio / 2), Top:=Shp_Mid - (CellHeight * FlowRatio / 2), Width:=CellHeight * FlowRatio, Height:=CellHeight * FlowRatio)
CircleCheck.Fill.ForeColor.RGB = RGB(234, 194, 130)
CircleCheck.Line.Weight = 0.75
CircleCheck.Line.ForeColor.RGB = RGB(255, 255, 255)
CircleCheck.Line.Visible = msoTrue
CircleCheck.LockAspectRatio = msoTrue
CircleCheck.Name = "CircleCheck " & CircleCheckCounter
CircleCheck.ZOrder msoBringToFront
ElseIf rng(i).Value < -12 Then
CellTop = newTable.cell(i, 1).Shape.Top:
CellLeft = newTable.cell(i, 1).Shape.Left
CellWidth = newTable.cell(i, 1).Shape.Width
CellHeight = newTable.cell(i, 1).Shape.Height
Shp_Cntr = CellLeft + CellWidth / 2
Shp_Mid = CellTop + CellHeight / 2
Set CircleCheck = sld.Shapes.AddShape(Type:=msoShapeOval, Left:=Shp_Cntr - (CellHeight * FlowRatio / 2), Top:=Shp_Mid - (CellHeight * FlowRatio / 2), Width:=CellHeight * FlowRatio, Height:=CellHeight * FlowRatio)
CircleCheck.Fill.ForeColor.RGB = RGB(104, 164, 144)
CircleCheck.Line.Weight = 0.75
CircleCheck.Line.ForeColor.RGB = RGB(255, 255, 255)
CircleCheck.Line.Visible = msoTrue
CircleCheck.LockAspectRatio = msoTrue
CircleCheck.Name = "CircleCheck " & CircleCheckCounter
CircleCheck.ZOrder msoBringToFront
End If
Next i
Next DataRow
End Sub
I need help locking the aspect ratio of images in a VBA code which pastes into an excel file images from links using information in specific cells.
What I would like to know is how to lock the aspect ratio of these pasted images.
I have tried to change things but haven't been able to succeed in keeping the aspect ratio.
Any help would be greatly appreciated! Thanks,
Peter
ActiveWindow.Zoom = 100
On Error Resume Next
Dim Plage As Range
Dim p As Object, t As Double, l As Double, w As Double, h As Double
Set Plage = Selection
lig = Plage.Cells(1).Row
col = Plage.Cells(1).Column
nbcel = 0
For Each cell In Plage
If cell.Value <> "" Then nbcel = nbcel + 1
Next cell
posColstr = InputBox("En quelle colonne voulez-vous inserer vos photos (1, 2, 3...)?", "Colonne", 1)
posCol = CInt(posColstr)
If posCol = 0 Then posCol = 1
For i = 0 To nbcel - 1
Matiere = Cells(i + lig, col).Value
Cells(i + lig, posCol).Activate
With Cells(i + lig, posCol)
t = .Top
l = .Left
w = .Width
h = .Height
End With
ActiveSheet.Shapes.AddPicture Filename:="https://websiteimagelink.com/" & Matiere & ".null.null.null.null.null.jpg", linktofile:=msoFalse, savewithdocument:=msoCTrue, Top:=t, Left:=l, Width:=70, Height:=50
ActiveSheet.Shapes(ActiveSheet.Shapes.Count).Placement = xlMoveAndSize
Next i
Here's an example of how you can do it.
Edited to show how it fits in your code.
Sub InsertPics()
Const MAX_WIDTH As Long = 100 'max picture width
Const MAX_HEIGHT As Long = 100 'max height
Dim Plage As Range, url, rngPic As Range
Dim p As Object, t As Double, l As Double, w As Double, h As Double
Set Plage = Selection
ActiveWindow.Zoom = 100
On Error Resume Next
posColstr = InputBox("En quelle colonne voulez-vous inserer vos photos (1, 2, 3...)?", "Colonne", 1)
posCol = CInt(posColstr)
If posCol = 0 Then posCol = 1
For Each c In Plage.Cells 'loop over user selection
Matiere = Trim(c.Value)
If Len(Matiere) > 0 Then 'if cell has a value...
url = "https://websiteimagelink.com/" & Matiere & ".null.null.null.null.null.jpg"
Set rngPic = c.EntireRow.Cells(posCol)
InsertResizePic rngPic, url, MAX_WIDTH, MAX_HEIGHT 'or rngpic.Width, rngpic.Height
End If
Next i
End Sub
'Insert a shape from path `pth`, positioned at cell `c`: resize so dimensions do
' not exceed `maxWidth` or `maxHeight`
Sub InsertResizePic(c As Range, pth As String, maxWidth As Long, maxHeight As Long)
Dim fW, fH, shp
Set shp = c.Parent.Pictures.Insert(Filename:=pth)
With shp
.ShapeRange.LockAspectRatio = msoTrue 'lock relative h/w
.Placement = xlMoveAndSize
.Top = c.Top
.Left = c.Left
fW = .Width / maxWidth 'dimensions relative to max allowed
fH = .Height / maxHeight
If fW > 1 Or fH > 1 Then 'is it too wide or too tall?
If fW >= fH Then
.Width = .Width / fW 'more too wide than too tall: shrink width
Else
.Height = .Height / fH 'shrink height
End If
End If
End With
End Sub
First time using this site. Borrowing an idea from the SpreadSheetGuru, I am copy and pasting bunch of drawn shapes into a temporary chart such that I can save them as a PNG image. I copy and paste different shapes, one by one, and then move them using Top and Left properties so they look like the original arrangement. It works great for rectangles and textboxes but gives me an error for lines (straight connectors). It says “the item with specified name wasn’t found” but I do not use anything different. I appreciate your help to solve this problem. Here is that part of the code below. The lines are copied and pasted, as I can see them when I step through the code, but cannot be "addressed" to be moved to their correct location on the chart
k = 0
For Each sh In ActiveSheet.Shapes ' ---------------------------------------- select one shape at a time
a1 = InStr(1, Trim(sh.Name), "TextBox", 1)
A2 = InStr(1, Trim(sh.Name), "Rectangle", 1)
a3 = InStr(1, Trim(sh.Name), "Straight", 1)
a4 = InStr(1, Trim(sh.Name), "Line", 1)
If a1 > 0 Or A2 > 0 Or a3 > 0 Or a4 > 0 Then
sh.Select
k = k + 1
Else: GoTo NextShape:
End If
sh.Name = sh.Name & k
'Copy/Paste Shape inside temporary chart
ActiveShape.Copy
cht.Activate
ActiveChart.Paste
ActiveChart.Shapes(UserSelection.Name).Top = ActiveShape.Top - Top0 ' === ERROR IS HERE
ActiveChart.Shapes(UserSelection.Name).Left = ActiveShape.Left - Left0
NextShape:
Next sh ' ----------------------------------------------------------------------
Here's a couple of different approaches. Both are pasting the shapes into a chart inserted on the worksheet (ie. I'm not using a chart sheet)
Sub CopyShapesToChart()
Dim sh, cht As Chart, e, shp, col As New Collection
Dim minY, minX, maxY, maxX, v
Set cht = ActiveSheet.ChartObjects(1).Chart
minY = 1000000# 'set starting points (random high number)
minX = 1000000#
'First collect all of the shapes we're interested in,
' and figure out the "bounding box" for them
For Each shp In ActiveSheet.Shapes
For Each e In Array("TextBox", "Rectangle", "Straight", "Line")
If InStr(1, shp.Name, e) > 0 Then
'tracking bounding box for all shapes
If shp.Top < minY Then minY = shp.Top
If shp.Left < minX Then minX = shp.Left
v = shp.Top + shp.Height
If v > maxY Then maxY = v
v = shp.Left + shp.Width
If v > maxX Then maxX = v
col.Add shp
Exit For
End If
Next e
Next shp
'resize the chartobject to fit the collection of shapes
cht.Parent.Height = maxY - minY
cht.Parent.Width = maxX - minX
'copy each shape into the chart
For Each shp In col
shp.Copy
cht.Paste
With cht.Shapes(cht.Shapes.Count)
.Top = shp.Top - minY
.Left = shp.Left - minX
End With
Next shp
'now export the chart...
End Sub
EDIT: a second approach with a little less work - instead of copying shapes one-by-one group all of them and copy them in one operation
Sub CopyShapesToChart2()
Dim sh, cht As Chart, e, shp
Dim arr(), ws As Worksheet, i As Long, rng
Set ws = ActiveSheet
Set cht = ws.ChartObjects(1).Chart
ReDim arr(0 To ws.Shapes.Count)
For Each shp In ws.Shapes
For Each e In Array("TextBox", "Rectangle", "Straight", "Line")
If InStr(1, shp.Name, e) > 0 Then
arr(i) = shp.Name
i = i + 1
Exit For
End If
Next e
Next shp
If i > 0 Then 'matched any shapes?
If i > 1 Then 'matched>1 shape?
ReDim Preserve arr(0 To i - 1)
Set rng = ws.Shapes.Range(arr).Group() 'group the matched shapes
Else
Set rng = ws.Shapes(arr(0)) 'just matched a single shape
End If
'resize the chartobject to fit the [collection of] shape[s]
cht.Parent.Height = rng.Height
cht.Parent.Width = rng.Width
rng.Copy 'copy the shape or group
cht.Paste
If i > 1 Then rng.Ungroup 'ungroup if we grouped anything
End If
End Sub
A friend of mine (Ray Hayes) provided the answer off line. To make the original code work, all is needed is to change "UserSelection.Name" to "Selection.Name".
Thanks #Rory! I was able to fix it and now I got a new bug
Run time error 1004/parameter not valid
at at .SeriesCollection(j).XValues = ws.Range(rs)
Could someone please help me?
'''
I am trying to make multiple charts. And each chart would have 20 different groups with legend.
The way I have tried is first make multiple charts by columns and then add for/n loop in my code (here tried to have every 20 rows for one each group
Sub horizontal()
Dim sh As Shape
Dim ws As Worksheet
Dim ch As Chart
Dim rd As Range
Dim i As Integer, j As Integer, k As Integer
Set ws = Sheets("S1")
On Error Resume Next
ws.ChartObjects.Delete
On Error GoTo 0
For i = 20 To 45
Set rs = ws.Range("s2:s21")
Set rd = ws.Range("f1:j10")
Set sh = ws.Shapes.AddChart2(240, xlXYScatterLines)
Set ch = sh.Chart
For j = 1 To 20
k = j * 20
With ch 'shape.chart'
.SetSourceData Union(rs, ws.Range(ws.Cells(2, i), ws.Cells(21, i)))
.SeriesCollection.NewSeries
.SeriesCollection(j).XValues = ws.Range("s2:s21")
.SeriesCollection(j).Values = ws.Range(ws.Cells(k - 18, i), ws.Cells(k + 1, i))
.HasTitle = True
.ChartTitle.Text = ws.Range("T1")
.HasLegend = True
End With
Next j
With sh
.Name = "cht" & (i - 19)
.Top = (i - 20) * rd.Height
.Left = rd.Left
.Width = rd.Width
.Height = rd.Height
End With
Next i
End Sub
I tried the below two codes but they didn'twork.
Sub horizontal()
Dim sh As Shape
Dim ws As Worksheet
Dim ch As Chart
Dim rd As Range
Dim i As Integer, j As Integer, k As Integer
Set ws = Sheets("S1")
On Error Resume Next
ws.ChartObjects.Delete
On Error GoTo 0
For i = 20 To 45
Set rs = ws.Range("s2:s21")
Set rd = ws.Range("f1:j10")
Set sh = ws.Shapes.AddChart2(240, xlXYScatterLines)
Set ch = sh.Chart
With ch 'shape.chart'
.SetSourceData Union(rs, Range(Cells(2, i), Cells(21, i)))
.HasTitle = True
.ChartTitle.Text = ws.Range("T1")
.HasLegend = True
End With
With sh
.Name = "cht" & (i - 19)
.Top = (i - 20) * rd.Height
.Left = rd.Left
.Width = rd.Width
.Height = rd.Height
End With
Next i
End Sub
Sub diameter()
Dim ws As Worksheet
Dim sh As Shape
Dim ch As Chart
Dim rng As Range, rngTime As Range
Dim n As Integer, m As Integer, k As Integer, i As Integer
Set ws = Sheets("S1")
'delete previous plots
If ws.ChartObjects.Count > 0 Then
ws.ChartObjects.Delete
End If
Set rngTime = ws.Range(Cells(2, 19), Cells(21, 19))
ws.Shapes.AddChart2(240, xlXYScatterLines).Select
ws.Shapes(1).Chart.SetSourceData Union(rngTime, Range(Cells(2, 20), Cells(21, 20)))
'Source:=Range("'S1'!$S$2:$S$21,'S1'!$T$2:$T$21")
For n = 1 To 20
m = n * 20
With ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(n).XValues = ws.Range(Cells(2, 19), Cells(21, 19))
ActiveChart.FullSeriesCollection(n).Values = ws.Range(Cells(m - 18, 20), Cells(m + 1, 20))
End With
Next n
End Sub
'''
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
This is what I have so far, I just can't figure out how to loop the pictures back after 10 rows.
Sub InsertPictures()
Dim PicList() As Variant
Dim PicFormat As String
Dim Rng As Range
Dim sShape As Shape
Dim MaxWidth#
On Error Resume Next
PicList = Application.GetOpenFilename(PicFormat, MultiSelect:=True)
xColIndex = Application.ActiveCell.Column
If IsArray(PicList) Then
xRowIndex = Application.ActiveCell.Row
For lLoop = LBound(PicList) To UBound(PicList)
Set Rng = Cells(xRowIndex, xColIndex)
With ActiveSheet.Shapes.AddPicture(PicList(lLoop), msoFalse, msoCTrue, Rng.Left, Rng.Top, -1, -1)
.LockAspectRatio = True
.Height = 100 * 3 / 4
Rng.RowHeight = .Height
If MaxWidth < .Width Then
MaxWidth = .Width
End If
End With
xRowIndex = xRowIndex + 1
Next
Rng.ColumnWidth = MaxWidth / Rng.Width * Rng.ColumnWidth
Rng.ColumnWidth = MaxWidth / Rng.Width * Rng.ColumnWidth
Rng.ColumnWidth = MaxWidth / Rng.Width * Rng.ColumnWidth
For Each sShape In ActiveSheet.Shapes
sShape.Left = MaxWidth / 2 - sShape.Width / 2
Next
End If
End Sub
Simply track xRowIndex change compared to original row. When it's > 10 different update row and column
Refactored (with a few other improvements)
Sub InsertPictures()
Dim PicList() As Variant
Dim PicFormat As String
Dim Rng As Range
Dim sShape As Shape
Dim MaxWidth#
Dim xColIndex As Long, xRowIndex As Long, lLoop As Long
Dim xColIncrement As Long, xRowInit As Long
Dim ws As Worksheet
Set ws = ActiveSheet ' <-- better to be explicit rather than rely on implicit ActiveSheet reference
'On Error Resume Next <-- dont just ignore all errors
PicList = Application.GetOpenFilename(PicFormat, MultiSelect:=True)
xColIncrement = 1 ' <-- adjust to how many columns to increment by
xColIndex = Application.ActiveCell.Column
xRowInit = Application.ActiveCell.Row
xRowIndex = xRowInit
With ws
If IsArray(PicList) Then
For lLoop = LBound(PicList) To UBound(PicList)
Set Rng = .Cells(xRowIndex, xColIndex)
With .Shapes.AddPicture(PicList(lLoop), msoFalse, msoCTrue, Rng.Left, Rng.Top, -1, -1)
.LockAspectRatio = True
.Height = 100 * 3 / 4
Rng.RowHeight = .Height
If MaxWidth < .Width Then
MaxWidth = .Width
End If
End With
xRowIndex = xRowIndex + 1
' Check if rows is > 10 different to initial row
If xRowIndex >= xRowInit + 10 Then
Rng.ColumnWidth = MaxWidth / Rng.Width * Rng.ColumnWidth
MaxWidth = 0
xColIndex = xColIndex + xColIncrement
xRowIndex = xRowInit
End If
Next
Rng.ColumnWidth = MaxWidth / Rng.Width * Rng.ColumnWidth
End If
End With
End Sub
Here is a bit simplified version:
Sub InsertPictures() ': DrawingObjects.Delete: Cells.Delete ' used for testing
Dim picList, pic, picFormat As String
Dim rng As Range, sShape As Shape, MaxWidth As Double
picList = Application.GetOpenFilename(picFormat, MultiSelect:=True)
If Not IsArray(picList) Then Exit Sub ' picList = False if no files selected
Set rng = ActiveCell
Application.ScreenUpdating = False ' optional to make it faster
For Each pic In picList
With Shapes.AddPicture(pic, 0, 1, rng.Left, rng.Top, -1, -1)
.LockAspectRatio = True
rng.RowHeight = rng.RowHeight * 10
.Height = rng.Height
If MaxWidth < .Width Then MaxWidth = .Width
End With
Set rng = rng(2) ' move to the cell below
Next
rng.ColumnWidth = MaxWidth * 255 / 1342.5
For Each sShape In Shapes
sShape.Left = rng.Left + (rng.Width - sShape.Width) / 2
Next
Application.ScreenUpdating = True
End Sub