Show dimensions of Excel shape in column widths and row heights vba - vba

I have a spreadsheet that involves the user resizing some rectangular shapes, which are set on a background of an Excel grid with column width = row height = 10pixels. The purpose of this background is to give a scale to the plan, which is made by the shapes; in this case, one column or row represents 10cm - there is a thick border after every 10 cells to represent a metre:
When the user resizes the rectangle, I would like the text inside the rectangle to display the dimensions, according to the scale of the plan. I have read many articles about how the shapes dimensions are provided in points, and the columns and rows in pixels (or a unit based on the font), and have found the conversion function between them, but it does not seem to give the results I would expect - the values for the width and height depend on the level of zoom, giving smaller and smaller results as I zoom out, even though the displayed pixel width remains the same.
Is there a way to consistently convert the pixel units of the grid to the points unit of the shapes such that I can essentially count how many column widths and row heights comprise the shape dimensions? Here is the macro I have written so far:
Option Explicit
Dim sh As Shape
Dim dbPx_Per_Unit As Double
Dim strUnit As String
Dim UserSelection As Variant
Dim strText As String
Dim strWidth As String
Dim strHeight As String
Sub LabelShapeSize()
Set UserSelection = ActiveWindow.Selection
'is selection a shape?
On Error GoTo NoShapeSelected
Set sh = ActiveSheet.Shapes(UserSelection.Name)
On Error Resume Next
'pixels are the units for the columns and rows
'dbPx_Per_Unit = InputBox("there are this many pixels per unit:", "Conversion Rate", 10)
dbPx_Per_Unit = 100
'strUnit = InputBox("Unit Name:", "Units", "M")
strUnit = "M"
With sh
'Width and length is measured in points, so we need to convert the points to pixels to get the actual size
strWidth = Format(Application.ActiveWindow.PointsToScreenPixelsX(.Width) / dbPx_Per_Unit, "#,##0.0")
strHeight = Format(Application.ActiveWindow.PointsToScreenPixelsY(.Height) / dbPx_Per_Unit, "#,##0.0")
'this is our message that will be in the shape
strText = strWidth & strUnit & " x " & strHeight & strUnit
With .TextFrame2
.VerticalAnchor = msoAnchorMiddle
With .TextRange.Characters
.ParagraphFormat.FirstLineIndent = 0
.ParagraphFormat.Alignment = msoAlignCenter
.Text = strText
'I'll sort something out for dark shapes at some point, but for now let's just write in black ink
With .Font
.Fill.Visible = msoTrue
.Fill.ForeColor.ObjectThemeColor = msoThemeColorDark1
.Fill.Solid
.Size = 10
End With
End With
End With
End With
Exit Sub
'No shape error
NoShapeSelected:
MsgBox "You must select a shape to calculate dimensions!", vbCritical, "Object not set to an instance of a Nobject"
End Sub
****** for completeness, here is the final script I wrote implementing the solution in the answer below ******
Option Explicit
Dim sh As Shape
Dim db_Cols_Per_Unit As Double
Dim strUnit As String
Dim strText As String
Dim userSelection As Variant
Dim ws As Worksheet
Dim clrBackground As Long
Dim leftCol As Integer
Dim colWidth As Integer
Dim topRow As Integer
Dim rowHeight As Integer
Sub LabelShapeSize()
Set userSelection = ActiveWindow.Selection
Set ws = ActiveSheet
db_Cols_Per_Unit = 10
strUnit = "M"
'is selection a shape?
On Error GoTo NoShapeSelected
Set sh = ActiveSheet.Shapes(userSelection.Name)
On Error Resume Next
topRow = 1
rowHeight = 0
leftCol = 1
colWidth = 0
With sh
While ws.Cells(1, leftCol).Left <= .Left 'Move left until we find the first column the shape lies within
leftCol = leftCol + 1
Wend
While ws.Cells(1, leftCol + colWidth).Left <= .Left + .Width 'Continue moving left until we find the first column the shape does not lie within
colWidth = colWidth + 1
Wend
While ws.Cells(topRow, 1).Top <= .Top 'Move down until we find the first row the shape lies within
topRow = topRow + 1
Wend
While ws.Cells(topRow + rowHeight, 1).Top <= .Top + .Height 'Continue moving down until we find the first row the shape does not lie within
rowHeight = rowHeight + 1
Wend
'this is our message that will be in the shape
strText = Format(colWidth / db_Cols_Per_Unit & strUnit, "#,##0.0") & " x " & rowHeight / Format(db_Cols_Per_Unit, "#,##0.0") & strUnit
clrBackground = .Fill.ForeColor.RGB
With .TextFrame2
.VerticalAnchor = msoAnchorMiddle
With .TextRange.Characters
.ParagraphFormat.FirstLineIndent = 0
.ParagraphFormat.Alignment = msoAlignCenter
.Text = strText
With .Font
.Fill.Visible = msoTrue
.Fill.ForeColor.RGB = ContrastColor(clrBackground)
.Fill.Solid
.Size = 10
End With
End With
End With
End With
Exit Sub
'No shape error
NoShapeSelected:
MsgBox "You must select a shape to calculate dimensions!", vbCritical, "Object not set to an instance of a Nobject"
End Sub
Function ContrastColor(clrBackground As Long) As Long
Dim brightness As Integer
Dim luminance As Double
Dim r As Integer
Dim g As Integer
Dim b As Integer
r = clrBackground Mod 256
g = (clrBackground \ 256) Mod 256
b = (clrBackground \ 65536) Mod 256
luminance = ((0.199 * r) + (0.587 * g) + (0.114 * b)) / 255
If luminance > 0.5 Then
brightness = 0
Else
brightness = 255
End If
ContrastColor = RGB(brightness, brightness, brightness)
End Function
thanks to #Gacek answer in this question for the luminance function.

I believe your best bet would be to make use of the Left, Top, Width, and Height cell properties. They'll tell you the value in Excel's weird format (the same units as used by the shapes), so you won't need to do any conversions.
The downside is that as far as I know of, there's no way to get the row/column that exists at a given top/left value, so you need to search through all the rows/columns until you find the one that matches your shape's boundaries.
Here's a quick example (there's probably an off-by-one error in here somewhere)
Dim UserSelection As Variant
Dim ws As Worksheet
Dim sh As Shape
Dim leftCol As Integer
Dim colWidth As Integer
Dim topRow As Integer
Dim rowHeight As Integer
Set ws = ActiveSheet
Set UserSelection = ActiveWindow.Selection
Set sh = ActiveSheet.Shapes(UserSelection.Name)
leftCol = 1
colWidth = 0
While ws.Cells(1, leftCol).Left <= sh.Left 'Move left until we find the first column the shape lies within
leftCol = leftCol + 1
Wend
While ws.Cells(1, leftCol + colWidth).Left <= sh.Left + sh.width 'Continue moving left until we find the first column the shape does not lie within
colWidth = colWidth + 1
Wend
topRow = 1
rowHeight = 0
While ws.Cells(topRow, 1).Top <= sh.Top 'Move down until we find the first row the shape lies within
topRow = topRow + 1
Wend
While ws.Cells(topRow + rowHeight, 1).Top <= sh.Top + sh.height 'Continue moving down until we find the first row the shape does not lie within
rowHeight = rowHeight + 1
Wend
MsgBox "Shape is " & colWidth & " columns wide by " & rowHeight & " rows high"

Related

Powerpoint layout algorithm for box-in-box view

I am trying to write some code in VBA and PowerPoint to automatically create a poster (basically a box in box view) however, its proving to be a little more challenging than my skills can cope.
looking to get some guidance on how best to structure the code (and patterns)
at the moment:
Im reading the data (see table) from csv, and placing them into 4 in memory arrays (cat, sub-cat, column, intersection) - this is probably bad - but dont know of anything better.
my code tries to process the spacing logic and adjusts the x-and-y pos of each intersection block (grows the category and sub-category blocks when needed) within the arrays, then finally draws/places the blocks on the powerpoint canvas.
You will see in the graphic "initial selected block" at the moment thats the context from which i run -- the idea is to use that block size as the template for the dimensions
Im not worried about the placement, its more the algorithm to determine the spacing (or block size of each of the components
below is a sample of the data that I read:
and once the logic is generated, this is how the "poster" would look
Im happy to share code, its just getting a bit big now (and I feel im missing a trick in terms of simplicity)
code sample included below:
Const defaultObjectWidth = 95
Const defaultObjectHeight = 50
Const defaultCategoryWidth = 90
Const defaultSubCatWidth = 90
Const defaultBuffer = 3
Const blocksPerCol = 4
Const myYAxisWidth = 100
Sub insertShape()
On Error GoTo Err_Handler
Dim SlideHeight As Long, SlideWidth As Long
Dim ContainerHeight As Long, ContainerWidth As Long
Dim ObjectHeight As Long, ObjectWidth As Long
Dim x As Long, y As Long
Dim shp As Object
Dim colWidth As Integer
Dim blockSize As Integer
Dim IntersectCalcComplete As Boolean
IntersectCalcComplete = False
' create the Arrays for storing the data
Dim CategorysArr() As String
Dim SubCatsArr() As String
Dim YAxissArr() As String
Dim IntersectsArr() As String
Dim tmpIntersects() As String
Call LoadSubCats(SubCatsArr)
Call LoadCategorys(CategorysArr)
Call LoadYAxiss(YAxissArr)
Call LoadIntersects(IntersectsArr)
ReDim tmpIntersects(0 To 2, 0 To 0)
If ActiveWindow.Selection.Type = ppSelectionNone Then
MsgBox "Please select object", vbExclamation, "Make Selection"
Else
Set shp = ActiveWindow.Selection.ShapeRange(1)
SlideHeight = ActivePresentation.PageSetup.SlideHeight 'get slide vertical height
SlideWidth = ActivePresentation.PageSetup.SlideWidth 'get slide horizontal width
'Main Content Container width and height
ContainerHeight = shp.Height
ContainerWidth = shp.Width
' calculate the container column sizes.
'
colWidth = calcColumnSizes(shp.Width, CategorysArr, SubCatsArr, YAxissArr)
' calculate the blockwidth based on the density factor parameter
blockWidth = calcBlockWidth(colWidth, blocksPerCol)
' Iterate through the Categorys, SubCats and Intersects in order to calculate the spacing of the Intersects.
' first sort the matricies by a specific column.
' CategorysArr = QuickSortArray(CategorysArr, -1, -1, 4)
' Call multiSortArray(1, CategorysArr, arrFlds(CategorysArr), "2 Asc 5 Asc")
' -- ------------------------------------------------------------------------------------------------------------------------------------------------
Dim SubCatID As Integer
'Dim myYAxisWidth As Integer
Dim SubCatHeight, CategoryHeight, currentX, currentY, n, t As Integer
SubCatHeight = 0
CategoryHeight = 0
currentX = 0
currentY = 0
currentBlockUsed = 0
For i = LBound(SubCatsArr, 2) To UBound(SubCatsArr, 2) ' For each SubCat in the SubCats Array
t = t + 1
'Debug.Print (" processing SubCat: " & t & " called: " & SubCatsArr(1, i))
' Debug.Print (SubCatsArr(i, 1)) ' print the name
SubCatID = SubCatsArr(0, i)
If Not IsNull(SubCatID) Then
' with each SubCat - find all related Intersects and fit them into the canvas
' 1: Filter the Intersects by SubCat
Call getIntersectBySubCat(SubCatID, IntersectsArr, tmpIntersects)
'printArray (tmpIntersects)
' 2: re-structure the Intersects position to fit into the YAxiss allocated
' myYAxisWidth = 200 ' -- get YAxis width TODO: get the real width
' -- we already know what the blockWidth is (above)
SubCatHeight = defaultObjectHeight + defaultBuffer ' set the SubCatheight on the first pass.
For j = LBound(tmpIntersects, 2) To UBound(tmpIntersects, 2) ' Loop through tmp Intersects to add placement
If LBound(tmpIntersects, 2) = -1 Then ' SubCat has no Intersects
' Debug.Print ("SubCat ID:" & SubCatID & " has no Intersects")
Else
If myYAxisWidth < (currentX + blockWidth + (defaultBuffer * 2)) Then ' If there is not enough remaining space in YAxis
currentY = currentY + defaultBuffer + defaultObjectHeight
currentX = 0
SubCatHeight = SubCatHeight + defaultObjectHeight + defaultBuffer
End If
n = findArrStr(IntersectsArr, 0, str(tmpIntersects(0, j)))
IntersectsArr(6, n) = str(currentX + defaultBuffer) ' X CoOrdinate
IntersectsArr(7, n) = str(currentY + defaultBuffer) ' Y CoOrdinate
currentX = currentX + defaultBuffer + defaultObjectWidth
End If
Next j 'filtered Intersect
Else
' Debug.Print ("empty record in Array Detected")
End If
Call setSubCatHeight(SubCatHeight, SubCatID, SubCatsArr, CategorysArr)
SubCatHeight = 0
Next i 'SubCat
' -- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' -- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' ADDING OF THE SHAPES TO THE VIEW
Call addCategorys(CategorysArr, shp)
Call addSubCats(SubCatsArr, shp)
Call addIntersects(IntersectsArr, shp)
' x = (SlideWidth - ObjectWidth) / 2 'calculate horizontal position
' y = (SlideHeight - ObjectHeight) / 2 'calculate vertical position
' shp.Left = x 'move object horizontal
' shp.Top = y 'move object vertical
End If
Exit_Label:
On Error Resume Next
Set shp = Nothing
Exit Sub
Err_Handler:
MsgBox Err.Description, vbCritical
Resume Exit_Label
End Sub
Function getIntersectBySubCat(SubCatID As Integer, ByRef IntersectsArr As Variant, ByRef tmpIntersects As Variant)
' Filters the Intersects to the specific SubCat
Dim i, j As Integer
j = -1
Erase tmpIntersects
ReDim Preserve tmpIntersects(0 To 2, -1 To 0)
For i = LBound(IntersectsArr, 2) To UBound(IntersectsArr, 2)
If IntersectsArr(2, i) = SubCatID Then 'if the Intersect relates to the current SubCat
j = j + 1
ReDim Preserve tmpIntersects(0 To 2, 0 To j) ' Redimension:
tmpIntersects(0, j) = IntersectsArr(0, i) ' Intersect Code
tmpIntersects(1, j) = IntersectsArr(3, i) ' get the YAxis
tmpIntersects(2, j) = IntersectsArr(9, i) ' get the Order
'Debug.Print ("RESULT ARRAY" & tmpIntersects(i + 1, 0) & "_" & tmpIntersects(i + 1, 1) & "_" & tmpIntersects(i + 1, 2) & "_")
End If
Next i 'Intersect
' sort the array by the Intersect order column (2)
' Call QuickSortArray(tmpIntersects, , , 2)
End Function
Function calcColumnSizes(lenContainer As Integer, ByRef CategorysArr As Variant, ByRef SubCatsArr As Variant, ByRef YAxissArr As Variant) As Integer
Dim lenCategory, lenSubCat, cntQtr As Integer
Dim lenWorkArea, columnSize As Integer
cntQtr = UBound(YAxissArr) + 1
lenWorkArea = lenContainer - defaultCategoryWidth - defaultSubCatWidth - (2 * defaultBuffer)
lenWorkArea = lenWorkArea - ((2 * defaultBuffer) + (cntQtr * defaultBuffer))
columnSize = lenWorkArea / cntQtr
' now propogate the columnSize into the YAxiss data
For i = LBound(YAxissArr, 1) To UBound(YAxissArr, 1)
YAxissArr(2, i) = str(Round(columnSize, 1)) ' Width
Next i
calcColumnSizes = columnSize
End Function
Function calcBlockWidth(columnSize As Integer, density As Integer) As Integer
calcBlockWidth = columnSize / density
End Function
Function setSubCatHeight(SubCatYPos, ID As Integer, ByRef SubCatsArr As Variant, ByRef CategorysArr As Variant)
Dim curSubCat As Integer
curSubCat = findArrStr(SubCatsArr, 0, str(ID))
If SubCatsArr(3, curSubCat) < SubCatYPos Then
SubCatsArr(3, curSubCat) = SubCatYPos
Call setCategoryHeight(SubCatYPos, CInt(SubCatsArr(2, curSubCat)), CategorysArr)
End If
End Function
Function setCategoryHeight(CategoryYPos, ID As Integer, ByRef CategorysArr As Variant)
Dim curCategory As Integer
curCategory = findArrStr(CategorysArr, 0, str(ID))
If CategorysArr(2, curCategory) < CategoryYPos Then
CategorysArr(2, curCategory) = CategoryYPos
End If
End Function
Function addCategorys(ByRef CategorysArr As Variant, masterShp As Shape)
Dim i, j As Integer
For i = LBound(CategorysArr, 2) To UBound(CategorysArr, 2)
Call addBlockContents(CInt(CategorysArr(2, i)), CInt(CategorysArr(3, i)), CStr(CategorysArr(1, i)), masterShp) ' X, Y, Name, Shape
Next i
End Function
Function addSubCats(ByRef SubCatsArr As Variant, masterShp As Shape)
Dim i, j As Integer
For i = LBound(SubCatsArr, 2) To UBound(SubCatsArr, 2)
Call addBlockContents(CInt(SubCatsArr(3, i)), CInt(SubCatsArr(4, i)), CStr(SubCatsArr(1, i)), masterShp)
Next i
End Function
Function addIntersects(ByRef IntersectsArr As Variant, masterShp As Shape)
Dim i, j As Integer
Dim myX, myY As Integer
myX = 0
myY = 0
For i = LBound(IntersectsArr, 2) To UBound(IntersectsArr, 2)
' adjust the placement of the shape relative to the masterShape
myX = masterShp.Left + CInt(IntersectsArr(6, i)) + defaultCategoryWidth + defaultSubCatWidth + (defaultBuffer * 2)
myY = masterShp.Top + CInt(IntersectsArr(7, i))
Call addBlockContents(myX, myY, CStr(IntersectsArr(1, i)), masterShp)
'For j = LBound(COAArray, 2) To UBound(COAArray, 2)
'Next j
Next i
End Function
Function addBlockContents(x, y, IntersectName As String, myShp As Shape)
Dim oSh As Shape
Set oSh = ActiveWindow.Selection.SlideRange.Shapes.AddShape(msoShapeRectangle, x, y, defaultObjectWidth, defaultObjectHeight)
With oSh
With .Fill
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText2
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0.8000000119
.Transparency = 0
.Solid
End With 'fill
With .TextFrame
.MarginLeft = 0
.MarginRight = 0
.MarginTop = 0
.MarginBottom = 0
.AutoSize = False
With .TextRange
.Text = IntersectName
With .Font
.Name = "Ariel"
.Size = 6.4
.Bold = msoFalse
.Italic = msoFalse
.Underline = msoFalse
.Shadow = msoFalse
.Emboss = msoFalse
.BaselineOffset = 0
.AutoRotateNumbers = msoFalse
.Color.SchemeColor = ppForeground
End With ' Font
End With ' TextRange
End With ' TextFrame
End With ' oSh, the shape itself
'Set addBlockContents = oSh
End Function
any help will be awesome!
The easiest way to get started here is to use tables. It will help you with a lot of the layout issues.
As a first step, create a table manually. Insert a table and remove headings and other automatic coloring. Set the border line to maximum width and to match the background color before applying it to all cells.
Now you can merge cells to create larger boxes (like Cars in your example). Deleting cells isn't possible, but you can set the background color.
If this is good enough, then you have something to automate.
If not, then you can perhaps use this to find coordinates for boxes to create.

Change text color as it's appended?

I'm going to be generating some large excel cell values by appending MS Project tasks info to each other, and then I'll be calculating if a certain task has changed since the last report. I need to color just the changed tasks in the cell, but it will be in a long string with lots of other tasks. It would be really nice if I could change the color of tasks as I append them.
I'm thinking I've got to use some sort of 'With' statement, but I don't where to start.
With cell
.FutureFormat red
.Value = .Value & "abc"
End With
Or something like
Stringthing = "ABC"
Stringthing.Format = red
Cell.value = cell.value & Stringthing
Here is an example code:
Option Explicit
Public Sub AppendStringAndColorize()
Dim str As String
str = "abc"
Dim cell As Range
Set cell = Range("A1")
Dim CellLength As Long
CellLength = Len(cell.Value)
With cell
.Value = .Value & str
.Characters(Start:=CellLength + 1, Length:=Len(str)).Font.Color = vbRed
End With
End Sub
you first need to remember the length of the original value as start point to colorize the characters after that value.
To keep the old colors:
Public Sub AppendStringAndColorizeKeepingOldColors()
Dim str As String
str = "abc"
Dim cell As Range
Set cell = Range("A1")
Dim CharList() As Variant
Dim CurrentColor As Double
CurrentColor = cell.Characters(1, 1).Font.Color
Dim iColor As Long 'color change counter
iColor = 1
ReDim CharList(1 To 2, 1 To 1) As Variant
CharList(1, iColor) = CurrentColor
Dim CellLength As Long
CellLength = cell.Characters.Count
'analyze colors and save into array
Dim i As Long
For i = 1 To CellLength
If cell.Characters(i, 1).Font.Color <> CurrentColor Then
CurrentColor = cell.Characters(i, 1).Font.Color
iColor = iColor + 1
ReDim Preserve CharList(1 To 2, 1 To iColor)
CharList(1, iColor) = CurrentColor
End If
CharList(2, iColor) = CharList(2, iColor) + 1
Next i
'change cell value (append only!)
cell.Value = cell.Value & str
're-write colors
Dim ActChar As Long
ActChar = 1
For i = LBound(CharList) To UBound(CharList, 2)
cell.Characters(Start:=ActChar, Length:=CharList(2, i)).Font.Color = CharList(1, i)
ActChar = ActChar + CharList(2, i)
Next i
'color for new appended string
cell.Characters(Start:=CellLength + 1, Length:=Len(str)).Font.Color = vbYellow 'desired color
End Sub
Here's how you add new text without disturbing the existing formatting.
NOTE: this approach is only good up to about 250 characters total length. Not sure if there's any way after you hit that point.
Public Sub Tester()
Const NUM As Long = 20
Const TXT As String = "The quick brown for jumped over the lazy dogs"
Dim colors, i, l
colors = Array(vbRed, vbBlue)
With ActiveSheet.Range("A1")
For i = 1 To NUM
l = Len(.Value)
'Error here if trying to access characters after ~250
With .Characters(Start:=l + 1, Length:=Len(TXT) + 1)
.Text = TXT & vbLf
.Font.Color = colors(i Mod 2)
End With
Next i
End With
End Sub

Find string in table VBA Powerpoint

After 2 days trying to find a solution to my problem, I need your help please.
I'm working on powerpoint VBA script, and I've got a Table (3,3). In the row 1, I've already input some string in cells.
I want to know why my script doesn't want to write NOK in cells when the string does'nt match "comp" for example
Here is my VBA script:
Public Sub CreateTable1()
' déclaration of variables
Dim objSld As Slide
Dim objShp As Shape
Dim foundText1 As Object
Dim FindWhat As String
Dim I As Integer
Dim j As Integer
Set objSld = ActivePresentation.Slides(1)
Set objShp = objSld.Shapes.AddTable(3, 3, 15, 150, 700, 500)
' Give a name to table
objShp.Name = "Table1"
' Define size of cells
With objSld.Shapes("Table1").Table
.Columns(1).Width = 115
.Columns(2).Width = 115
.Columns(3).Width = 115
.Rows(1).Height = 120
.Rows(2).Height = 120
.Rows(3).Height = 120
'Write in cells
With .Cell(1, 1).Shape.TextFrame
.TextRange.Text = "Composition"
End With
With .Cell(2, 1).Shape.TextFrame
.TextRange.Text = "Material"
End With
With .Cell(3, 1).Shape.TextFrame
.TextRange.Text = "Method"
End With
' Define text position
For I = 1 To 3
For j = 1 To 3
With .Cell(j, I).Shape.TextFrame
.VerticalAnchor = msoAnchorMiddle
.HorizontalAnchor = msoAnchorCenter
.TextRange.Font.Size = 18
End With
Next j
Next I
'Command find
'Browse row 1 from line 1 to 3
For x = 1 To 3
Set foundText1 = objSld.Shapes("Table1").Table.Cell(x, 1).Shape.TextFrame.TextRange.Find(FindWhat:="Comp")
If foundText1 = "Comp" Then
'MsgBox foundText1 & x
'Will write in cell (x,2) OK and x
objSld.Shapes("Table1").Table.Cell(x, 2).Shape.TextFrame.TextRange.Text = "OK " & x
Else
'Will write in cell (x,2) NOK and x
'Doesn't works !! Why??
objSld.Shapes("Table1").Table.Cell(x, 2).Shape.TextFrame.TextRange.Text = "NOK " & x
End If
Next x
End With
End Sub
I Would like to know if you see where is the mistake. The function Else seems not working..
I found the solution !!
For those who're lost with this same problem, here is my code:
Public Sub CreateTable1()
' déclaration of variables
Dim objSld As Slide
Dim objShp As Shape
Dim foundText1 As Object
Dim TextRng As TextRange
Dim FindWhat As String
Dim I As Integer
Dim j As Integer
Set objSld = ActivePresentation.Slides(8)
Set objShp = objSld.Shapes.AddTable(3, 3, 15, 150, 700, 500)
' Give a name to table
objShp.Name = "Table1"
' Define size of cells
With objSld.Shapes("Table1").Table
.Columns(1).Width = 115
.Columns(2).Width = 115
.Columns(3).Width = 115
.Rows(1).Height = 120
.Rows(2).Height = 120
.Rows(3).Height = 120
'Write in cells
With .Cell(1, 1).Shape.TextFrame
.TextRange.Text = "Composition"
End With
With .Cell(2, 1).Shape.TextFrame
.TextRange.Text = "Material"
End With
With .Cell(3, 1).Shape.TextFrame
.TextRange.Text = "Method"
End With
' Define text position
For I = 1 To 3
For j = 1 To 3
With .Cell(j, I).Shape.TextFrame
.VerticalAnchor = msoAnchorMiddle
.HorizontalAnchor = msoAnchorCenter
.TextRange.Font.Size = 18
End With
Next j
Next I
'Command find
'Browse row 1 from line 1 to 3
End With
End Sub
Creation of a second sub to understand where does script failed
Sub yolo()
Dim objSld As Slide
Dim oTbl As Table
Dim lRow As Long
Dim lCol As Long
Dim foundText1 As Object
Set objSld = ActivePresentation.Slides(8)
Set oTbl = objSld.Shapes("Table1").Table
With oTbl
For lRow = 1 To .Rows.Count
With .Cell(lRow, 1).Shape
'Do something with each cell's text
'Does this shape has text?
If .HasTextFrame Then
Set TextRng = oTbl.Cell(lRow, 1).Shape.TextFrame.TextRange
Set foundText1 = TextRng.Find(FindWhat:="Comp")
Do While Not (foundText1 Is Nothing)
With foundText1
oTbl.Cell(lRow, 2).Shape.TextFrame.TextRange.Text = "OK"
Set foundText1 = TextRng.Find(FindWhat:="Comp", After:=.Start + .Length - 1)
End With
Loop
End If
End With
Next lRow
End With
End Sub

chartArea position properties don't work in vba Excel 2013

I'm noob in vba (Excel macros). I need to add somes charts automatically in the same WorkSheet. This is my code:
Sub runChart()
Dim xchart As Chart
Dim nameSheet As String
nameSheet = ActiveSheet.Name
Dim x As Integer
Dim firstIndex As Integer
Dim firstValue As Integer
Dim actualValue As Integer
Dim actualIndex As Integer
Dim rChart1 As Range
Dim rChart2 As Range
MsgBox nameSheet
firstIndex = 2
actualIndex = 2
firstValue = Cells(2, 1)
actualValue = Cells(2, 1)
Do
Do
actualIndex = actualIndex + 1
actualValue = Sheets(nameSheet).Cells(actualIndex, 1)
Loop Until firstValue <> actualValue
Set rChart1 = Range(Sheets(nameSheet).Cells(firstIndex, "E"), Sheets(nameSheet).Cells(actualIndex - 1, "E"))
Set rChart1 = Union(rChart1, Range(Sheets(nameSheet).Cells(firstIndex, "J"), Sheets(nameSheet).Cells(actualIndex - 1, "J")))
Dim nameChart As String
nameChart = CStr(Sheets(nameSheet).Cells(firstIndex, 5)) & " - " & Sheets(nameSheet).Cells(actualIndex, 5) & " " & CStr(Sheets(nameSheet).Cells(firstIndex, 1))
Set xchart = Charts.Add
With xchart
.Name = nameChart
.ChartType = xlColumnClustered
.SetSourceData rChart1
.Location Where:=xlLocationAsObject, Name:=nameSheet
'position and size chart
.ChartArea.Top = 10 'this position is a example
.ChartArea.Left = 1700 'this position is a example
.ChartArea.Height = 400 'this size is a example
.ChartArea.Width = 750 'this size is a example
End With
firstValue = Sheets(nameSheet).Cells(actualIndex, 1)
firstIndex = actualIndex
Loop Until (Sheets(nameSheet).Cells(actualIndex, 1) = vbNullString)
End Sub
So, my problem happens is in .ChartArea.left = 1700. The program says :
The specified dimension is not valid for the current chart type
anyone has any idea what 's happening? Thanks for your time :)
The ChartArea is the overall rectangle containing the chart within its parent ChartObject (the shape that contains the embedded chart). The position and size of the ChartArea are read only. But that's okay, you want to position and resize the ChartObject, which is the chart's .Parent.
With xchart
'position and size chart
.Parent.Top = 10 'this position is a example
.Parent.Left = 1700 'this position is a example
.Parent.Height = 400 'this size is a example
.Parent.Width = 750 'this size is a example
End With

Autofit Cell Size (both rows and columns) after pasting an image

I have been working on this code where I need to take input of images from my PC, paste them in a certain column, and then resize the cells according to the image size. Following is the code, I am using:
Sub BBS()
Dim file As Variant
Dim r As Integer
Dim ID As Integer
For r = 1 To 6
ID = Cells(r, 1).Value
file = "D:\" & ID & ".jpg"
If Dir(file) = "" Then
Else
With ActiveSheet.Pictures.Insert(file)
.Left = ActiveSheet.Cells(r, 5).Left
.Top = ActiveSheet.Cells(r, 5).Top
End With
End If
Next r
Call Resize
End Sub
Sub Resize()
Worksheets("Sheet1").Columns("A:I").AutoFit
Worksheets("Sheet1").Rows("1:10").AutoFit
End Sub
The images are getting pasted, but I'm not able to adjust the cell size.
That's because the picture is not in the cell - it has merely been placed in the worksheet at the position of the cell.
Try in in Excel itself (not the VBA window). You are essentially inserting a picture, moving it so that it matches up with the top-left coordinates of a cell, and then trying to AutoFit. (Nothing will happen to the cell).
You can 'fudge' it by setting the size of your pictures using this:
Sub BBS()
Dim file As Variant
Dim r As Integer
Dim ID As Integer
For r = 1 To 6
ID = Cells(r, 1).Value
file = "D:\" & ID & ".jpg"
If Not Dir(file) = "" Then
With ActiveSheet.
.AddPicture file, msoFalse, msoTrue, _
ActiveSheet.Cells(r, 5).Left, ActiveSheet.Cells(r, 5).Top, 100, 100
End With
End If
Next r
Call Resize
End Sub
Sub Resize()
Worksheets("Sheet1").Columns("A:I").ColumnWidth = 18.29
Worksheets("Sheet1").Rows("1:10").RowHeight = 100
End Sub
Note that the scales used by .AddPicture and ColumnWidth / RowHeight are not the same. You'll have to experiment here.
Updated
Sub BBS()
Dim r As Integer
Dim ID As Integer
Dim ws As Worksheet
Dim objShell As New Shell
Dim objFolder As Folder
Dim objFile As ShellFolderItem
Dim strDimensions As String
Dim intPos As Integer 'Position of first space in strDimensions
Dim intWidth As Integer
Dim intHeight As Integer
Dim intWidthMax As Integer
Set objFolder = objShell.Namespace("D:\")
Set ws = ActiveSheet
intWidthMax = 0
For r = 1 To 3
ID = Cells(r, 1).Value
Set objFile = objFolder.ParseName(ID & ".jpg")
strDimensions = objFile.ExtendedProperty("Dimensions")
intPos = InStr(1, strDimensions, " ", vbTextCompare)
'These next variables contain the dimensions of the image in pixels.
intWidth = CInt(Mid(strDimensions, 2, intPos - 2))
intHeight = CInt(Mid(strDimensions, intPos + 3, Len(strDimensions) - intPos - 3))
With ActiveSheet.Shapes
'Here we treat the dimension values (which are actually in pixels) as points.
'The conversions depend on your DPI, so you could play around with a scaling
'factor here.
.AddPicture objFile.Path, msoFalse, msoTrue, ActiveSheet.Cells(r, 5).Left, _
ActiveSheet.Cells(r, 5).Top, intWidth, intHeight
End With
'RowHeight is done in points, so it will match the height of your images.
ws.Rows(r).RowHeight = intHeight
If intWidth > intWidthMax Then intWidthMax = intWidth
Next r
'Set column width to widest image width.
'Width points are different from height points.
'5.29 as a conversion works for me (and my DPI).
ws.Columns(5).ColumnWidth = intWidthMax / 5.29
End Sub