Error moving lines/circles in CATIA drawing with VBA macro - vba

I am writing a macro handling a title block in Catia drawings.
I have subs that I use to move circles and lines, which work fine (code initially found here)
Private Sub moveCircle(oCircle, dX As Double, dY As Double)
Dim oCtr(1)
oCircle.GetCenter oCtr
movePoint oCircle.CenterPoint, dX, dY
movePoint oCircle.StartPoint, dX, dY
movePoint oCircle.EndPoint, dX, dY
oCircle.SetData oCtr(0) + dX, oCtr(1) + dY, oCircle.Radius
Debug.Print "move circle OK"
End Sub
Private Sub movePoint(oPt, dX As Double, dY As Double)
Dim oCoord(1)
oPt.GetCoordinates oCoord
oPt.SetData oCoord(0) + dX, oCoord(1) + dY
End Sub
Private Sub moveLine(oLine, dX As Double, dY As Double)
Dim oStartPt As Variant
Dim oEndPt As Point2D
Dim myDir(1)
Dim oPtCoord(1)
oLine.GetDirection myDir
Set oStartPt = oLine.StartPoint
Set oEndPt = oLine.EndPoint
movePoint oStartPt, dX, dY
movePoint oEndPt, dX, dY
oStartPt.GetCoordinates oPtCoord
oLine.SetData oPtCoord(0), oPtCoord(1), myDir(0), myDir(1)
End Sub
So those functions are called in a sub called "DrawView" when I create the drawing to move stuff around depending on the paper format, and everything works well.
If the paper format is changed later on, I want to resize everything and call those functions again from another sub "resizeTitleBlock", exactly the same way, and this is when it doesn't work anymore. I get an error saying the the method SetData in sub movePoint failed.
Those functions are called in both cases like this:
Dim element
For Each element In refView.GeometricElements
Select Case TypeName(element)
Case "Axis2D":
'nothing to do, must be excldued
Case "Line2D":
moveLine element, sheetWidth - 210, 0
Case "Circle2D":
moveCircle element, sheetWidth - 210, 0
End Select
Next element
Any idea what may cause this issue?
I tried checking that the elements I pass to those functions are the same in both cases (by checking the name of the element). From Sub DrawView, "Line.1" is moved properly. From Sub resizeTitleBlock, I pass "Line.1" to the function again and get the error "the method SetData has failed".
I tried calling calling moveLine from Sub DrawView several times, and it works.

Related

How to automatically arrange shapes automatically drawn by loop?

I have a loop that generates rectangles automatically on a visio drawing but I need to have the script to arrange them automatically right know I recorded a macro while I rearranged the rectangles manually under the title box. But my rectangle count change constantly because the results from my if statement change constantly because my data continuously changes. I need for my loop to start drawing them under the title box in columns of six or seven rectangles.
For I = 1 To WS_Count
Set vsoShape =
Application.ActiveWindow.Page.Drop(Application.DefaultRectangleDataObject,
aoffset, boffset)
vsoShape.Text = ActiveWorkbook.Worksheets(I).Name
aoffset = aoffset
boffset = boffset + 0.75
Dev_Count = Dev_Count + 1
ActiveDocument.DiagramServicesEnabled = DiagramServices
Next I
I need to be able to set a starting position to begin dropping the rectangles below the title rectangle creating a new column every six to seven rectangles. Thanks
Increment aOffset every time I is divisible by the number of shapes you want horizontally...
You can do this with the Mod Operator If (iterator Mod runEveryXIterations = 0) Then ...
The example below should clarify the idea, the code is not exactly what you need but you should be able to grasp the idea:
Option Explicit
Public Sub printXY()
xyDistribute 10, 3, 0, 0, 0.75, 1.5
End Sub
Private Function xyDistribute(ByRef iterations As Long, _
ByRef newColAfter As Long, _
ByRef xPosInitial As Double, _
ByRef yPosInitial As Double, _
ByRef xStep As Double, _
ByRef yStep As Double)
Dim iter As Long
Dim xPos As Double
Dim yPos As Double
yPos = yPosInitial
xPos = xPosInitial
Debug.Print "xPos", "yPos"
For iter = 1 To iterations
Debug.Print xPos, yPos
' your code goes here
If (iter Mod newColAfter = 0) Then
yPos = yPos + yStep
xPos = xPosInitial
Else
xPos = xPos + xStep
End If
Next iter
End Function

mouse controlled by an IMU

I am using pitch and yaw angle from an IMU to move a mouse pointer for PC in vb.net.
Unfortunately it doesn't work steady.
First I set the max angles which should be performed
LOAD-Event
'set max angles in degree
maxAngle_YawRight = 30
maxAngle_YawLeft = -30
maxAngle_PitchUp = 20
maxAngle_PitchDown = -20
calculateCurParameter(maxAngle_YawRight, Panel_Right.Location.X, maxAngle_YawLeft, Panel_Left.Location.X + Panel_Left.Width, maxAngle_PitchUp, Panel_Top.Location.Y+Panel_Top.Height, maxAngle_NickDown, Panel_Bottom.Location.Y)
I use four these max angles (pitch_up, pitch_down, yaw_right, yaw_left) to assign them to a part of my form, to get 4 points, e.g. (pitch_up,panel_2.location.Y)
pitch_up and pitch_down are used for the y coordinate of the mouse pointer and yaw_right and yaw_left are used for the x coordinate. This is done by function calculateCurParameter.
Then I use this four points to calculate parameters for an linear equation:
CursorPos=m*angle+b
So you get for every new angle a new Cursor Position.
Private mX As Double
Private bX As Double
Private mY As Double
Private bY As Double
...
Private Sub calculateCurParameter(ByVal maxYawRight As Double, ByVal rightBorder As Double, ByVal maxYawLeft As Double, ByVal leftBorder As Double, ByVal maxPitchUp As Double, ByVal topBorder As Double, ByVal maxPitchDown As Double, ByVal bottomBorder As Double)
'this function calculates the parameter for Ycur=m*Xangle+b for each Pitch and Yaw
'calculate the parameter for the CursorPosition X
dim deltaX= maxYawLeft-maxYawRight
dim deltaY=leftBorder-rightBorder
mX=deltaY/deltaX
bX=rightBorder-mX*maxYawRight
'calculate the parameter for the CursorPosition Y
deltaX=bottomBorder-topBorder
deltaY=maxPitchDown-maxPitchUp
mY=deltaY/deltaX
bY=topBorder-mY*maxPitchUp
end Sub
After that calculation, I use a quadratic weighted moving average (QWMA) as a low pass filter cursor outputs calculated by the function y=m*x+b.
For that moving average I use the last 50 samples of each angle.
After that I put the two angles in each linear equation(cursorPos=m*angle+b) as described.
'Timer-Event which is triggered each 8ms
' yaw and pitch are in degrees and are updated in this timer event before
Dim xCoordCur = Math.Round(mX * yaw + bX)
Dim yCoordCur = Math.Round(mY * pitch + bY)
arrayCurY(cursorCounter) = yCoordCur
arrayCurX(cursorCounter) = xCoordCur
If cursorCounter =50 Then 'need 50 samples to do the QWMA
Dim aqwmY = qwma_calculating(arrayCurY)'function to calculate the QWMA, seems to be working
Dim aqwmX = qwma_calculating(arrayCurX)
'the mouse pointer should not leave the form
If aqwmX > Panel_Right.Location.X Then
aqwmX = Panel_Right.Location.X
ElseIf aqwmX < (Panel_Left.Location.X + Panel_Left.Width) Then
aqwmX = Panel_Left.Location.X + Panel_Left.Width
End If
If aqwmY > Panel_Bottom.Location.Y Then
aqwmY = Panel_Bottom.Location.Y
ElseIf aqwmY < (Panel_Top.Location.Y + Panel_Top.Height) Then
aqwmY = Panel_Top.Location.Y + Panel_Top.Height
End If
'Set the new Cursor Position
Cursor.Position = New Point(aqwmX, aqwmY)
arrayValuesMoving(arrayCurX)'function to move the values one index forward
arrayValuesMoving(arrayCurY)
Else
cursorCounter += 1
End If
In the my last step I set the new Cursor-Position
Cursor.Position=New Point(xCoor,yCoor)
Now I can control the mouse pointer by moving the IMU, but it is very unstable.
For example the mouse pointer still moves although the IMU doesn't move.
It's even impossible to hover over some form elements.
What did I do wrong?
Thanks in advance!
I added the follwoing code:
If xCoor > Cursor.Position.X + 3 Or xCoor < Cursor.Position.X - 3 Then
istxCoor = True
Else
istxCoor = False
End If
If yCoor > Cursor.Position.Y + 3 Or yCoor < Cursor.Position.Y - 3 Then
istyCoor = True
Else
istyCoor = False
End If
If istxCoor And istyCoor Then
SetCursorPos(xCoor, yCoor)
ElseIf istxCoor Then
SetCursorPos(xCoor, Cursor.Position.Y)
ElseIf istyCoor Then
SetCursorPos(Cursor.Position.X, yCoor)
End If
it is now more steady but it has now a time lag.

Mouse down event timing

I've been asked to code the ability to click on an image in Excel and add a shape on top of it (it's a body diagram for a physiotherapist, the shape will indicate the site of the patient's pain). My code does this OK by using the mouse down event of an ActiveX image control:
Private Sub bodypic_MouseDown(ByVal Button As Integer, _
ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
ClickShape x, y
End Sub
Sub ClickShape(x As Single, y As Single)
Dim shp As Shape
Dim cursor As Point
Set shp = ActiveSheet.Shapes.AddShape(msoShapeMathMultiply, x + ActiveSheet.Shapes("bodypic").Left, _
y + ActiveSheet.Shapes("bodypic").Top, 26, 26)
With shp.Fill
.ForeColor.RGB = RGB(255, 0, 0)
.BackColor.RGB = RGB(255, 0, 0)
End With
shp.Line.Visible = False
End Sub
The problem is that while the mouse cursor is over the diagram the shape is not visible. Only when the mouse is moved off of the diagram does the shape appear.
I've tried various methods to refresh the screen, selecting a cell, even changing the cursor position via the SetCursor method in Lib user32. Nothing seems to work except for the user actually moving the mouse.
To recreate the issue: insert an ActiveX image control roughly 200 x 500 px, add a jpeg image to the control, add the mouse down code to the worksheet and the click shape code to a module.
This is very hacky but I discovered that hiding and unhiding the image solves the problem:
ActiveSheet.Shapes("bodypic").Visible = False
ActiveSheet.Shapes("bodypic").Visible = True
End Sub
I'd welcome more elegant answers!
I have a limited amount of success with this code:-
Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Integer
Sub ClickShape(ByVal x As Single, ByVal y As Single)
Dim Shp As Shape
Dim Pos As POINTAPI
GetCursorPos Pos
SetCursorPos Pos.x + 300, Pos.y
With ActiveSheet
With .Shapes("bodypic")
x = x + .Left
y = y + .Top
End With
Set Shp = .Shapes.AddShape(msoShapeMathMultiply, x, y, 26, 26)
End With
With Shp
.Name = "Mark1"
.Line.Visible = False
With .Fill
.ForeColor.RGB = RGB(255, 0, 0)
.BackColor.RGB = RGB(255, 0, 0)
End With
End With
End Sub
In essence, what it does is to move the cursor out of the image. Then it takes about a second for the mark to appear. The delay will be longer the more marks there are. Note that my movement of 300 pixels is random. You would have to work out where to move it, so long as it is outside the image. I tried moving it back immediately, but that didn't work, and timing the return would be tricky because of the variations in the delay.
I experimented with another concept where I created the mark first and made it invisible. Then, on MouseUp (MouseUp is the more suitable event), I moved the mark and made it visible. That was faster, but it limits you to a single mark or condemns you to a lot of name management. Giving a name to the mark is a leftover from that experiment. Actually, it looked quite nice since I could move the mark by repeatedly clicking on different positions. If you need only one mark I recommend to pursue that idea.
If you need several marks, another leftover from my experiments is the idea to add a feature to delete (or hide) a mark, perhaps on double-click.

CorelDraw X6 Macro to insert Date using DTPicker Control

I'm trying to insert a date into a label. I have written the following code. I can select a date by clicking on the arrow and the calendar pops up. The "CANCEL" button is working, but when I click "OK" I cannot get it to insert on the label. The label is a regular Corel document with text and images. I tried inserting a rectangle toolbox to see if I can get it to insert the date in there by using X,Y coordinates but that didn't work.
I basically need to know how to insert DTPicker.Value onto the label.
Sub ShowIt()
Calendar.Show
End Sub
Private Sub Cancel_Click()
Unload Me
End Sub
Private Sub OK_Click()
a = DTPicker1.Value
b = Format(DTPicker1.Value, "mm/dd/yy")
Unload Me
End Sub
Private Sub DTPicker1_CallbackKeyDown(ByVal KeyCode As Integer, ByVal Shift As Integer, ByVal CallbackField As String, CallbackDate As Date)
DTPicker1.Value = Format(DTPicker1.Value, "mm/dd/yy")
End Sub
Private Sub Calendar_Activate()
Me.DTPicker1.Value = Date
End Sub
Thank you!
Try to run the previous code separated from your code.
Sub Macro1()
ActiveDocument.ReferencePoint = cdrCenter
XPos = Activeselection.PositionX
YPos = Activeselection.PositionY
Set s = ActiveLayer.CreateArtisticText(0, 0, CStr(Date))
s.PositionX=XPos
s.PositionY=YPos
End Sub
Select the rectangle
Click macro
The macro should work perfectly to create and place date at center on rectangle. BUT, the date is NOW (date when macro executed).
Then you should modify " CStr(Date)" to the value where the date is referred.
Try This :
1. Add a button on macro form
2. Select the rectangle
3. Click the button
4. Macro will read X, Y Pos of the rectangle, then create text and positioning it on the center of the rectangle
ActiveDocument.ReferencePoint = cdrCenter
XPos = Activeselection.PositionX 'XPos of the rect
YPos = Activeselection.PositionY 'YPos of the rect
Set s = ActiveLayer.CreateArtisticText(0, 0, CStr(Date))
s.PositionX=XPos
s.PositionY=YPos
The below code should work as requested :
ActiveDocument.ReferencePoint = cdrCenter
XPos = Activeselection.PositionX 'XPos of the rect
YPos = Activeselection.PositionY 'YPos of the rect
Set s = ActiveLayer.CreateArtisticText(0, 0, CStr(Date))
s.PositionX=XPos
s.PositionY=YPos
BUT :
He did not use Corel Draw..... :)
https://community.coreldraw.com/talk/coreldraw_community/f/101/t/51007
"Object variable or With block variable not set".
No Active document there.
I think you should create NEW Document first

Find power point animation step vba

I have a vba script that runs during presentation on a slide on a power point presentation. On the same slide, I have an animation. The script is running fine "in the background" when the animation is run, but at a certain step of the animation, I would like to change how the vba-script is run. Either by checking the timeline object or somewhere else to check how far the animation has been run, or by triggering an event when reaching the correct step, but I have not been able to find anything.
This is my script at the moment (illustrating a radioactive source, sending out radiation in all directions)
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Running As Boolean ' Switched on or off by another sub
Sub DrawLines()
Dim endx As Long
Dim endy As Long
Dim Slideid As Long
Dim tetha As Double
Dim origx As Long
Dim origy As Long
Dim linelength As Long
Dim tl As TimeLine
Slideid = 2
origx = 100
origy = 430
linelength = 2000
Dim newline As Shape
While Running
With ActivePresentation.Slides(Slideid).Shapes
tetha = 2 * 3.1415 * Rnd()
endx = Int(linelength * Sin(tetha))
endy = Int(linelength * Cos(tetha))
' Here I want to alter endx and endy after a certain step in the animation
Dim sleeptime As Long
sleeptime = Int(500 * Rnd())
Set newline = .AddLine(origx, origy, endx, endy)
DoEvents ' needed to redraw
Sleep (30)
newline.Delete
DoEvents ' needed to redraw
Sleep (sleeptime)
End With
Wend
End Sub
At the point where I would like to alter endx and endy, I have been looking for something either like
IF Activepresentation.slides(slideid).timeline.activestep>=5 THEN
dosomething()
End if
or if I could make something like
Public Changed as boolean
Sub OnSlideShowAnimationStep( .... )
IF currentstep >=5
Changed = TRUE
end if
end sub
and then I can check for Changed in drawlines, but I can neither find any attribute telling me the current animation step nor any event that is fired on animation steps. Any other places I should have looked?
If the animations are On Click you can use SlideShowWindow(1),View.GetClickCount
Otherwise you can maybe use OnSlideShowNextBuild(ByVal Wn As SlideShowWindow) to count
I don't know about any events or ways of checking on what step or where on the timeline
but you have one hack that might fix this.
when you are in your loop you can always check for the (left, top) position of the shape. And that changes while the animation run.
But on the other hand you might be able to manually iterate the animation by using the MoveTo function of the Effect object.
MSDN
But I haven't used that myself.