VBA scroll to text (search result) - excel

I have a function which searchs through all the textboxes in a file and when it finds the text it automatically scrolls the window to the shape that contains the text.
Is it possible to:
a) scroll to the text, instead of the shape (scroll the page and center it on the search text result)
b) if not possible, then scroll to the middle of the shape (now it's going to the top)
If InStr(LCase(sTemp), LCase(sFind)) <> 0 Then
shp.Select
With shp.Line
.ForeColor.RGB = vbRed
.Weight = 5
End With
sFind2 = LCase(sFind)
sTemp2 = LCase(shp.TextFrame.Characters.Text)
iPos2 = InStr(sTemp2, sFind2)
If iPos2 > 0 Then
With shp.TextFrame.Characters(Start:=iPos2, _
Length:=Len(sFind2)).Font
.Size = 35
End With
End If
shp.Select
ActiveWindow.ScrollRow = shp.TopLeftCell.Row
ActiveWindow.ScrollColumn = shp.TopLeftCell.Column
End If
Useless to say: I am not an expert, sorry for the bad formatting.

a) you cannot scroll to a text. You can just scroll full rows and full columns.
b) you can do that only approximately, because you can just scroll full rows and full columns.
Since shp.TopLeftCell finds the top left cell under the shape, you can try to use the height/width of the shape and cells to find the cell that is approximately in the middle of the shape.
'scroll additional rows
Dim CellHeights As Double
CellHeights = shp.TopLeftCell.Height
Dim iRow As Long
Do While CellHeights < shp.Height / 2
CellHeights = CellHeights + shp.TopLeftCell.Offset(RowOffset:=iRow).Height
iRow = iRow + 1
Loop
ActiveWindow.ScrollRow = shp.TopLeftCell.Offset(RowOffset:=iRow).Row
'scroll additional columns
Dim CellWidths As Double
CellWidths = shp.TopLeftCell.Width
Dim iCol As Long
Do While CellWidths < shp.Width / 2
CellWidths = CellWidths + shp.TopLeftCell.Offset(ColumnOffset:=iCol).Width
iCol = iCol + 1
Loop
ActiveWindow.ScrollColumn = shp.TopLeftCell.Offset(ColumnOffset:=iCol).Column

Related

Paste Pictures and Organize

I have the following code, which sorts some pictures down according to a value in Sheet1. Horizontally the images are aligned in the required columns. But not in the Rows.
I tried to do it with another FOR loop that I called J but doesn't work, it puts the images on top of each other.
How can I align the pictures in a column and a row that I choose?
What am I doing wrong? or what am I missing?
Thank you.
-------------CODE-------------
Sub CommandButton2_Click()
Dim firma_pic As Picture
Dim pic_location As String
Dim identifier_pic As String
'For j = 14 To 23
'Next
'Worksheets("Sheet3").Cells(14, 23).Select
For i = 2 To 11
identifier_pic = Worksheets("Sheet1").Cells(i, 11).Value
pic_location = "C:\Users\User\Downloads\Docs\img\" & Worksheets("Sheet1").Cells(i, 2).Value & ".png"
With Worksheets("Sheet3").Cells(i, 24)
Set firma_pic = ActiveSheet.Pictures.Insert(pic_location)
firma_pic.Top = .Top
firma_pic.Left = .Left
firma_pic.ShapeRange.LockAspectRatio = msoFalse
firma_pic.Placement = xlMoveAndSize
firma_pic.ShapeRange.Width = 70
firma_pic.ShapeRange.Height = 30
End With
Next
Worksheets("Sheet3").Cells(i, 23).Select
End Sub
Width and Height need to consider your cell too. You may resize images and force them to be W=70 and H=30 where the cell begins, but it could lead to images overlapping between columns. I'd suggest you to stick to the same workflow as you did for Top and Left
firma_pic.ShapeRange.Width = .Width
firma_pic.ShapeRange.Height = .Height

Move image to a specific location on a sheet

I have 12 pictures that I've dragged and dropped into the sheet directly from a windows folder. They are named "1 1.bmp", "1 2.bmp", "1 3.bmp" and so on.
I want to move them but how?
This is the code I'm trying:
Worksheets("R").Shapes("1 1").Top = Worksheets("R").Rows(24).Top
I don't know how reference to them. They are in the same folder as the .xlsm file. I've tried
Worksheets("R").Shapes("1 1.bmp").Top = Worksheets("R").Rows(24).Top
too.
Both examples from another question here on stack overflow.
What is the correct syntax?
/Jens
Here is the code to first insert picture to Excel and then adjust or resize the Picture. Later move the Picture towards down or right:
'Insert the Picture from the path if its not present already
Set myPict = Thisworkbook.sheets(1).Range("A1:B5").Parent.Pictures.Insert(ThisWorkbook.Path & "\" & "mypic.jpg")
'Adjust the Picture location
myPict.Top = .Top
myPict.Width = .Width
myPict.Height = .Height
myPict.Left = .Left
myPict.Placement = xlMoveAndSize
'myPict.LockAspectRatio = msoTriStateMixed
'Change the width of the Picture
myPict.Width = 85
'change the Height of the Picutre
myPict.Height = 85
End With
'Select the Picutre
myPict.Select
'Move down the picture to 3 points. Negative value move up
Selection.ShapeRange.IncrementTop 3
'Move towards right upto 5 points. Negative value moves towards right
Selection.ShapeRange.IncrementLeft 5
Try this code:
Option Explicit
Sub ArrangePictures()
Dim sh As Shape, anchor_cell As Range, v_shift As Long
With Worksheets("R")
Set anchor_cell = .Range("B24") 'left top corner for pictures
v_shift = 0 'vertical shift for next picture
For Each sh In .Shapes 'loop over all the shapes in the sheet
If sh.Type = msoPicture Then 'check if the shape is a picture
sh.Top = anchor_cell.Top + v_shift 'move picture (vertical)
sh.Left = anchor_cell.Left 'move picture (horizontal)
v_shift = v_shift + sh.Height 'add vertical shift for next picture
End If
Next
End With
End Sub

Set cell size equal to picture size

I'm trying to import a picture to excel cell and I'm facing issues with re-sizing.
Steps:
Copy/Paste the picture to the cell
Re-size the picture manually
And also resize the cell to fix on the picture.
Is there any other way to do it instead of manually?
I'm not sure what exactly you meant with re size the picture manually, but might this be working for you?
Sub ResizeCells()
Dim X As Double, Y As Double, Z As Double
Dim s As Shape
For Each s In ActiveSheet.Shapes
If s.Type = msoPicture Then
For X = s.TopLeftCell.Column To s.BottomRightCell.Column
Y = Y + ActiveSheet.Cells(1, X).ColumnWidth
Next X
For X = s.TopLeftCell.Row To s.BottomRightCell.Row
Z = Z + ActiveSheet.Cells(1, X).RowHeight
Next X
s.TopLeftCell.ColumnWidth = Y
s.TopLeftCell.RowHeight = Z
End If
Next s
End Sub
Note:
Max RowHeight is 409
Max ColumnWidth is 255
This goes the other way.
We will insert a Shape from the Internet.
We will move it to cell B1.
We will resize the Shape (both height and width) to fit in B1First place this link in cell A1:
http://www.dogbreedinfo.com/images26/PugPurebredDogFawnBlackMax8YearsOld1.jpg
Then run:
Sub MAIN()
Call InstallPicture
Call PlaceAndSizeShape
End Sub
Sub InstallPicture()
Dim v As String
v = Cells(1, 1).Value
With ActiveSheet.Pictures
.Insert (v)
End With
End Sub
Sub PlaceAndSizeShape()
Dim s As Shape, B1 As Range, w As Double, h As Double
Set s = ActiveSheet.Shapes(1)
s.Select
Selection.ShapeRange.LockAspectRatio = msoFalse
Set B1 = Range("B1")
s.Top = B1.Top
s.Left = B1.Left
s.Height = B1.Height
s.Width = B1.Width
End Sub
This post is old, but nobody mentioned resizing the picture to match the cell.
Excel is very unreliable when I tired to scale the width using #Andrew's code. Luckily, rCell.Left is in the correct units. You can get the actual column width using:
rCell.Offset(0, 1).Left - rCell.Left
This Code will Resize the Cell to Your Picture
Sub ResizePictureCells()
For Each Picture In ActiveSheet.DrawingObjects
PictureTop = Picture.Top
PictureLeft = Picture.Left
PictureHeight = Picture.Height
PictureWidth = Picture.Width
For N = 2 To 256
If Columns(N).Left > PictureLeft Then
PictureColumn = N - 1
Exit For
End If
Next N
For N = 2 To 65536
If Rows(N).Top > PictureTop Then
PictureRow = N - 1
Exit For
End If
Next N
Rows(PictureRow).RowHeight = PictureHeight
Columns(PictureColumn).ColumnWidth = PictureWidth * (54.29 / 288)
Picture.Top = Cells(PictureRow, PictureColumn).Top
Picture.Left = Cells(PictureRow, PictureColumn).Left
Next Picture
End Sub

Why does a for-loop to resize an image run well at $A$1 but otherwise gives a height and/or width of 0?

My code resizes an image. If the image's TopLeftCell is $A$1, it will work. However, if it is any other cell the width or height ends up being 0.
It is supposed to be running through two functions: getCellHeight and getCellWidth to grab the total height and width of merged cells, but it will also work with non-merged cells as long as the TopLeftCell is $A$1.
When working with non-merged cells:
Anything $A$n where n is greater than 1 results in a width with 0
height.
Anything $(n)$1 where n is greater than A results in a height with 0
width.
Anything $(n)$(m) where n is greater than A and m is greater than 1
results in 0 height and 0 width.
When working with merged cells:
The functionality is similar to non-merged cells, the difference being that on $(n)$(m) it will only run the height and width for loops if:
The number of rows merged is >= 9. At 9 rows, the for loop for
counting rows will run a single time.
The number of columns merged is >= 7. At 7 columns, the for loop for
counting columns will run a single time.
Anything below 9 rows results in 0 height, anything below 7 rows
results in 0 width.
Here is the code:
Sub TestCode()
If TypeOf Selection Is Picture Then
Call ResizeSingleImage(Selection)
ElseIf TypeOf Selection Is DrawingObjects Then
Call ResizeMultipleImages(Selection)
ElseIf TypeOf Selection Is Range Then
MsgBox ("Please make sure an image is selected.")
Exit Sub
End If
End Sub
Function ResizeMultipleImages(ByRef refPictures)
For Each refPic In refPictures
Call ResizeSingleImage(refPic)
Next
End Function
Function ResizeSingleImage(ByRef refPicture)
refPicture.ShapeRange.LockAspectRatio = msoTrue
MsgBox ("TopLeftCell: " & refPicture.TopLeftCell.Address)
tempWidth = getCellWidth(refPicture.TopLeftCell)
tempHeight = getCellHeight(refPicture.TopLeftCell)
MsgBox ("Width and Height: " & tempWidth & " " & tempHeight)
If tempWidth > tempHeight Then
refPicture.Height = tempHeight
Else
refPicture.Width = tempWidth
End If
End Function
Function getCellHeight(ByRef cellRef As Range) As Single
curColumn = cellRef.Column
curRow = cellRef.Row
numOfRows = cellRef.MergeArea.Rows.Count
totalHeight = 0
MsgBox (cellRef.Address & " Rows: " & numOfRows)
MsgBox ("Cell Height: " & cellRef.Height)
For cRow = curRow To numOfRows
MsgBox ("In Row For Loop")
totalHeight = totalHeight + Cells(curColumn, cRow).Height
Next
getCellHeight = totalHeight
End Function
Function getCellWidth(ByRef cellRef As Range) As Single
MsgBox (cellRef.Address)
curColumn = cellRef.Column
curRow = cellRef.Row
numOfColumns = cellRef.MergeArea.Columns.Count
totalWidth = 0
For col = curColumn To numOfColumns
MsgBox ("In Column For Loop")
totalWidth = totalWidth + Cells(curRow, col).Width
Next
MsgBox (cellRef.Address & " Columns: " & numOfColumns)
getCellWidth = totalWidth
End Function
Tested:
Sub Tester()
ResizeSingleImage ActiveSheet.Shapes(1)
End Sub
Sub ResizeSingleImage(ByRef refPicture)
Dim rng As Range, tempWidth, tempHeight
Set rng = refPicture.TopLeftCell.MergeArea
refPicture.Top = rng.Top
refPicture.Left = rng.Left
tempWidth = rng.Width
tempHeight = rng.Height
refPicture.LockAspectRatio = msoTrue
'which dimension to resize?
If tempWidth / refPicture.Width > tempHeight / refPicture.Height Then
refPicture.Height = tempHeight
Else
refPicture.Width = tempWidth
End If
End Sub
The problem with your original looping: let's say cellRef is A5
Function getCellHeight(ByRef cellRef As Range) As Single
curColumn = cellRef.Column
curRow = cellRef.Row '<< for A5 curRow = 5
numOfRows = cellRef.MergeArea.Rows.Count '<< let's say 4 rows
totalHeight = 0
MsgBox (cellRef.Address & " Rows: " & numOfRows)
MsgBox ("Cell Height: " & cellRef.Height)
For cRow = curRow To numOfRows '<<<<this loops from 5 to 4....
'code in loop doesn't execute....
MsgBox ("In Row For Loop")
totalHeight = totalHeight + Cells(curColumn, cRow).Height
Next
getCellHeight = totalHeight
End Function
So there are two answers here, the first one is going to be the best solution, thanks to Tim Williams, the second is going to be the solution to the actual problem I was originally facing.
The first (best) solution
Use .MergeArea.Height on the Range object.
It is quite obvious and is the most straightforward solution. I used the looping solution because when I originally looked up how to find the height and width of a merged cell, the loop was what came up through searches and I assumed properties didn't exist.
The second solution using loop
The issue is in the how the For-loop is setup. For cRow = curRow To numOfRows where curRow is the current row, making it so if you are at row 11 and the number of rows merged is only 3, the loop will never run. My solution to this was For cRow = curRow To (curRow + numOfRows - 1). This will get you the same result, but it goes to show why the use of properties is preferred over re-building the wheel.

Drawing a chart with owc chartspace in userform vba excel

I have a little problem with my owc chartspace, I would like to draw a chart like in the picture but my problem is that it draws only for one series I would like to draw it for the 1 the 2 and the 3 I don't know how to do this.
I have a listbox and a combobox, I select from the list box the 1,2,3 and I select from the combobx y or z such that x is fixed.
Then I put the data in plage(1) for x and plage(2) for y but the problem is that it works only for the first item I select from the listbox ( in this picture the "1" )
Could you tell what is wrong in my code?
the vba code for drawing the chart into the userform is:
Private Sub drow()
Dim i, k As Integer, x As Integer
Dim j As Integer
Dim Table(), Plage(2)
Dim id As Integer
id = 1
Do While ComboBox.Value <> idi(id, 1)
id = id + 1
Loop
For i = Cht.SeriesCollection.Count To 1 Step -1
Cht.SeriesCollection.Delete i - 1
Next i
k = 1
ReDim Table(ListBox.ListCount)
For i = 0 To ListBox.ListCount - 1
If ListBox.Selected(i) = True Then
Table(k) = ListBox.List(i)
k = k + 1
End If
Next i
With Cht
.HasLegend = True
.Legend.Position = chLegendPositionBottom
.HasTitle = True
.Title.Caption = ComboBox.Text
End With
Cht.Type = C.chChartTypeColumnClustered3D
With Cht
'first serie
.SeriesCollection.Add
.SeriesCollection(0).Caption = sheet.Cells(2, 15 + id)
.SeriesCollection(0).DataLabelsCollection.Add
.SeriesCollection(0).DataLabelsCollection(0).Position = chLabelPositionCenter
.SeriesCollection(0).DataLabelsCollection(0).Font.Color = RGB(255, 255, 255)
.SeriesCollection.Add
.SeriesCollection(1).Caption = sheet.Cells(2, 20) .SeriesCollection(1).DataLabelsCollection.Add
.SeriesCollection(1).DataLabelsCollection(0).Position = chLabelPositionCenter
.SeriesCollection(1).DataLabelsCollection(0).Font.Color = RGB(255, 255, 255)
.SetData C1.chDimCategories, C1.chDataLiteral, Table
End With
For j = 0 To ListBox.ListCount - 1
If ListBox.Selected(j) = True Then
Plage(1) = sheet.Cells(j + 3, 15 + id) 'the Xs
Plage(2) = sheet.Cells(j + 3, 20) 'Les 'the Ys
With Cht
.SeriesCollection(0).SetData C1.chDimValues, C1.chDataLiteral, Plage(1)
.SeriesCollection(1).SetData C1.chDimValues, C1.chDataLiteral, Plage(2)
End With
Erase Plage
End If
Next j
End Sub
I am very new to the whole owc and VB thing and I am having some troubles myself, but have you tried using C1.chDimXValues and C1.chDimYValues instead of the chDimValues in the below statement:
.SeriesCollection(0).SetData
C1.chDimValues, C1.chDataLiteral,
Plage(1) .SeriesCollection(1).SetData
C1.chDimValues, C1.chDataLiteral,
Plage(2)
Sorry if this might sound trivial, I can see your coding skills are much more advanced than mine. Good luck!

Resources