Increment the length of a copied motion path using VBA - vba

I am trying to create a row of duplicated objects in PowerPoint, each with a motion path that is slightly shorter than the next, like this:
First Image
I know that you cannot add a path animation from scratch in VBA, so I used VBA to copy and paste an object and its motion path, then edit the motion path.
This is my VBA code:
Sub CopyPastePosition()
' Copy the shape in slide 2 which has a custom motion path aleady
ActivePresentation.Slides(2).Shapes(3).Copy
Dim x As Integer
' For loop - create 5 duplicates
For x = 1 To 5
' Each duplicate is nudged to the left by x*100
With ActivePresentation.Slides(1).Shapes.Paste
.Name = "Smiley"
.Left = x * 100
.Top = 1
End With
' This is where I am unsure - I want the motion path to be longer by x amount each time
ActivePresentation.Slides(1).TimeLine.MainSequence(x).Behaviors(1).MotionEffect.Path = "M 0 0 L 0 x*0.7"
Next x
End Sub
However, the output is like this:
Second Image

Path property for motion path which represents a VML string. The VML string is a collection of coordinates for a Line or Bezier curve (for
powerpoint purposes). The values are fractions of the slide dimensions.
You can generate an incrementing VML path with this function.
Function GetPath(MaxSegments As Integer, Increment As Single)
Dim path As String
Dim i As Integer
path = "M 0 0 "
For i = 1 To MaxSegments
path = path & "L 0 " & CStr(Increment * i) & " "
Next
path = path & " E"
GetPath = path
End Function
Since you are doing copy/paste of a shape with motion path already on it, I would also make this change to ensure we reference the correct motion path upon paste:
With ActivePresentation.Slides(1).TimeLine
.MainSequence(.MainSequence.Count).Behaviors(1).MotionEffect.path = GetPath(x, 0.7)
End With

Yes, I realise that I am trying to insert a variable into a string. yes the correct way of doing this is "M 0 0 L 0 " & (x * 0.7)
Thank you #braX

Related

Using iText7.Net, why dimensions returned by iText.Kernel.Geom.Point are 10 times greater that TextRenderInfo.LineSegment.GetStartPoint()?

I written a VB.Net program that intercept RENDER_PATH and RENDER_TEXT events generated by iText7 module.
I have written a little code to find location of TEXT.
Dim ascent As LineSegment = t.GetAscentLine()
Dim descent As LineSegment = t.GetDescentLine()
Dim initX As Single = descent.GetStartPoint().Get(0)
Dim initY As Single = descent.GetStartPoint().Get(1)
Dim endX As Single = ascent.GetEndPoint().Get(0)
Dim endY As Single = ascent.GetEndPoint().Get(1)
For specific PDF page, all values returned by GetStartPoint() and GetEndPoint() are between 20 and 600.
To find PATH values, I have writte following code
Private Sub RenderPath(render As PathRenderInfo)
For Each sp As Subpath In render.GetPath().GetSubpaths()
Console.WriteLine(render.GetPath().ToString())
For Each segment In sp.GetSegments()
Console.WriteLine(" " & segment.ToString())
Select Case segment.GetType().FullName
Case "iText.Kernel.Geom.Line"
Dim oLine As iText.Kernel.Geom.Line = segment
Dim oList As List(Of Point) = oLine.GetBasePoints()
Dim n = 0
For Each p In oList
Console.WriteLine(" p" & CStr(n) & ".x: " & CStr(oList(n).GetX()))
Console.WriteLine(" p" & CStr(n) & ".y: " & CStr(oList(n).GetY()))
n += 1
Next
Console.WriteLine(" width: " & CStr(oList(0).GetX() - oList(1).GetX()))
Console.WriteLine(" height: " & CStr(oList(0).GetY() - oList(1).GetY()))
Case "iText.Kernel.Geom.BezierCurve"
Case Else
Dim i0 = 0
End Select
Next
Next
End Sub
All location's values returned by GetX() and GetY() functions are now between ... 200 and 6000 !
Why PATH location's values seems to be 10 times greater that TEXT location's values ?
Is that normal or is that a BUG ?
In iText7, what are dimensions of TEXT locations and dimensions of PATH segments ?
In iText7, what are dimensions of TEXT locations and dimensions of PATH segments ?
Indeed, the coordinates returned by TextRenderInfo and those returned by PathRenderInfo differ:
Coordinates returned by TextRenderInfo are given in the default user space coordinates of the given page, i.e. all active transformations are already accounted for.
Coordinates returned by PathRenderInfo, on the other hand, are given in the current user space coordinates - current when the path is constructed and drawn. To transform these coordinates into default user space coordinates, you have to apply the CTM (current transformation matrix) to the path. You can retrieve the CTM using the GetCTM method of the path render info object.
That different render info classes return coordinates in conceptually different coordinate system probably isn't intuitive and should be made clearer.
In case of your document page the CTM appears to be a scaling transformation by a factor of 0.1.

trouble with interrupting a Batch file started with VBA

I have an Excel file with a lot of PC's names in a server, I want to execute the "systeminfo" command and get the OS out of it. Then the OS shall be put into an Excel cell automatically. To do so, I used the following codes, respectively in the VBA file and the batch file.
however, whenever the server can't reach a pc, the cmd window is stuck until I manually close it. Since the list is actually 148 names long, knowing of a way to automatically close those Windows after, say, 8 seconds would be really helpful.
I tried to look up for a way to multi-thread VBA, just to find out that It is a single-threaded Language. I then tried to start another batch file with the one I'm actually using as to forcefuly kill it afetr a set of time, but it seems that the second batch starts only after the first is terminated, making it useless.
VBA
Sub Test()
'
' Test Macro
' I'm not an expert in VBA, I just picked it up for this task, so a lot of code will result redundant. Bear with me
'
'
Dim i As Integer
'a is basically i-1.
a = 1
' I needed 148 cells for the project
Dim models(1 To 147) As String
For i = 2 To 148
models(a) = Cells(i, 3).Value
a = a + 1
Next i
a = 1
For i = 2 To 148
'not totally sure what the next five lines actually do, but "metodo" is the name of the batch file.
Dim strShellCommand As String
strShellCommand = "C:\Users\Administrator\Desktop\metodo.bat " + models(a)
Set oSh = CreateObject("WScript.Shell")
Set oEx = oSh.Exec(strShellCommand)
strBuf = oEx.StdOut.readAll
'I took out of the string everything that wasn't purely the OS name
Dim FinalString As String
FinalString = Right(strBuf, 26)
FinalString = Left(FinalString, 25)
'this is the line that prints the OS names into Excel cells
ActiveSheet.Cells(i, 10) = FinalString
a = a + 1
Next i
End Sub
then there is the Batch file
set nome=%1
shift
systeminfo /s %nome% |findstr /c:"Microsoft Windows "
u can do a control loop after the Set oEx = oSh.Exec(strShellCommand)
like :
Set oEx = oSh.Exec(strShellCommand)
LoopCount = 0
Do 'Control loop
wscript.Sleep 1000
If TimeOut > 0 Then LoopCount = LoopCount + 1
Loop Until (oEx.Status <> 0) Or (LoopCount > TimeOut * 8)
If oEx.Status = 0 Then 'Timeout occured
oEx.Terminate
ReturnValue = "[Process terminated after timeout!]" & VbCrLf
Else
ReturnValue = "[Process completed]" & VbCrLf
End If
each loop takes 1 second (wscript.Sleep 1000) and the (LoopCount > TimeOut * 8) sets the total time to 8 seconds
good luck

Referring to variables, using variables

I'm creating a game, which will store maps on separate files.
This is done in that file using variables as such:
Public X1Y1 = "idle"
Containing the location and pixel information for my screen drawing engine.
To draw each pixel, I need to cycle through all of these variables.
I wanted to do that as shown, but I can't figure out how to refer to the variables in the map file(eg: X1Y1 or X5Y4), using a variable which stores the name of the variable required (pos).
Dim targetmap As SplashMap = New SplashMap()
For rowcount = 0 To targetmap.xRes Step 1
'for each row on the map
For columncount = 0 To targetmap.yRes Step 1
'place the pixel in each column
Dim pos = "X" & rowcount & "Y" & columncount
PlacePixel(pos, targetmap.'var <- problem, vbNull)
'call engine(Pixel Location, Pixel information stored in var, special control instruction (unused))
Next
Next

Excel VBA-Getting a blank message box with data derrived from an array

I am getting a blank message box for an array which should automatically have and display the following values:
00:00:00
01:00:00
02:00:00
and so on...
Here is my code
Dim i As Integer
i = 0
Dim sampleArr(0 To 24) As Variant
Dim a As Integer
a = 0
Do Until i > 23
sampleArr(a) = i & ":00:00"
a = a + 1
i = i + 1
MsgBox sampleArr(a)
Loop
Please tell me what's wrong with this code
You update the value of sampleArr(a), then increment a. So to get the just-updated value you need to use the pre-incremented value: a-1.
MsgBox sampleArr(a-1)
Put the Msgbox first before you increment a and i.
MsgBox sampleArr(a)
a = a + 1
i = i + 1
It's not entirely clear what you're trying to achieve here, (especially with a and i being identical. Presumably the msgbox is only actually in there to prove you've created the array correctly and will be removed later?
That said, as everyone is pointing out, you're incrementing your pointer before displaying the entry. The simplest way to fix that is to put the display line in immediately after creating the element.
I've also formatted i in order to produce the exact output you've requested.
Also, I suspect your array only needs to go 0 To 23 if this is some kind of time selector?
So, fixing your issue looks like:
Dim i As Integer
i = 0
Dim sampleArr(0 To 23) As Variant
Dim a As Integer
a = 0
Do Until i > 23
sampleArr(a) = Format(i, "00") & ":00:00"
MsgBox sampleArr(a)
a = a + 1
i = i + 1
Loop
However, you could just do the following:
Dim i As Integer
Dim sampleArr(0 To 23) As Variant
For i = 0 To 23
sampleArr(a) = Format(i, "00") & ":00:00"
MsgBox sampleArr(a)
Next
Beyond this, if you want to store the values in the array as TIME rather than a text representation of the time (useful for calculations etc.) then replace the sampleArr line with
sampleArr(a) = TimeSerial(i, 0, 0)

When does VBA change variable type without being asked to?

I am getting a runtime error I don't understand in Excel 2011 for Mac under OS X 10.7.5. Here is a summary of the code:
Dim h, n, k as Integer
Dim report as Workbook
Dim r1 as Worksheet
Dim t, newline as String
Dim line() as String
newline = vbCr
'
' (code to get user input from a text box, to select a worksheet by number)
'
ReDim line(report.Sheets.Count + 10)
MsgBox "Array line has " & UBound(line) & " elements." '----> 21 elements
line = split(t, newline)
h = UBound(line)
MsgBox "Array line has " & h & " elements." '----> 16 elements
n = 0
MsgBox TypeName(n) '----> Integer
For k = h To 1 Step -1
If IsNumeric(line(k)) Then
n = line(k)
Exit For
End If
Next k
If n > 0 Then
MsgBox n '----> 7
MsgBox TypeName(n) '----> String
Set r1 = report.Sheets(n) '----> Runtime error "Subscript out of bounds"
So n is declared as an integer, but now VBA thinks it is a string and looks for a worksheet named "7". Is this a platform bug, or is there something I haven't learned yet?
It also surprises me that putting data into the dynamic array reduces its dimension, but perhaps that is normal, or perhaps for dynamic arrays Ubound returns the last used element instead of the dimension, although I have not seen that documented.
The first part of your question is answered by #ScottCraner in the comments - the correct syntax for declaring multiple strongly typed variables on one line is:
Dim h As Integer, n As Integer, k As Integer
'...
Dim t As String, newline As String
So, I'll address the second part of your question specific to UBound - unless you've declared Option Base 1 at the top of the module, your arrays start at element 0 by default, not element 1. However, the Split function always returns a 0 based array (unless you split a vbNullString, in which case you get a LBound of -1):
Private Sub ArrayBounds()
Dim foo() As String
'Always returns 3, regardless of Option Base:
foo = Split("zero,one,two,three", ",")
MsgBox UBound(foo)
ReDim foo(4)
'Option Base 1 returns 1,4
'Option Base 0 (default) returns 0,3
MsgBox LBound(foo) & "," & UBound(foo)
End Sub
That means this line is extremely misleading...
h = UBound(line)
MsgBox "Array line has " & h & " elements."
...because the Array line actually has h + 1 elements, which means that your loop here...
For k = h To 1 Step -1
If IsNumeric(line(k)) Then
n = line(k)
Exit For
End If
Next k
...is actually skipping element 0. You don't really even need the h variable at all - you can just make your loop parameter this...
For k = UBound(line) To LBound(line) Step -1
If IsNumeric(line(k)) Then
n = line(k)
Exit For
End If
Next k
...and not have to worry what the base of the array is.
BTW, not asked, but storing vbCr as a variable here...
newline = vbCr
...isn't necessary at all, and opens the door for all kinds of other problems if you intend that a "newline" is always vbCr. Just use the pre-defined constant vbCr directly.