I have multi shapes.
I want to show all dimensions of each sides(the green lines).
I want to use vba.
I can show dimension a full square or rectangle shape.
for example to show a horizontal dimension I use this function:
Function createDimensionHorizental(x1, y1, x2, y2)
' This example creates an aligned dimension in model space and
' uses the TextHeight property to increase the height of the
' dimension text
Dim dimObj As AcadDimAligned
Dim point1(0 To 2) As Double, point2(0 To 2) As Double
Dim location(0 To 2) As Double
' Define the dimension
point1(0) = x1: point1(1) = y1: point1(2) = 0
point2(0) = x2: point2(1) = y1: point2(2) = 0
location(0) = x1: location(1) = y1 + 10: location(2) = 0
' Create an aligned dimension object in model space
Set dimObj = ThisDrawing.ModelSpace.AddDimAligned(point1, point2, location)
' Read and display current dimension text height
'MsgBox "The dimension text height for this object is currently set to: " & dimObj.TextHeight
' Increase the distance of the dimension gap
'Format the dimension object according to your needs.
With dimObj
.TextHeight = 30
.TextGap = 10 'The distance of the dimension text from the dimension line.
.Arrowhead1Type = 5 'acArrowOblique in early binding
.Arrowhead2Type = 5 'For the standard dimension arrow put 0 here.
.ArrowheadSize = 20
.ExtensionLineExtend = 10 'The amount to extend the extension line beyond the dimension line.
End With
ThisDrawing.Regen acAllViewports
End Function
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.
I am trying to create a Sankey-diagram in Excel, and as a start to this, I am trying to create some "entry arrows" for the left part of the diagram, which will look roughly like this:
I created it by making a chevron arrow, and dragging the rightmost points of it to line up with the tip of the arrow.
Now, to do this for all the arrows I need, I want to do this programmatically, but I can't figure out if there is any way to do much with the nodes (?) of the shape. Trying to record a macro gave me nothing.
This is what I have so far, the macro aborts on the Debug.Print line, probably because the node object doesn't have a Left property :P
Sub energiInn()
Dim r As Range, c As Range
Dim lo As ListObject
Dim topp As Double, høgde As Double
Dim i As Long, farge As Long
Dim nd As Object
Set lo = Tabell.ListObjects("Energi_inn_elektrolyse")
Set r = lo.DataBodyRange
topp = 50
With SankeyDiagram.Shapes
For i = 1 To r.Rows.Count
høgde = Application.WorksheetFunction.Max(10, r.Cells(i, 2) / 50#)
With .AddShape(Type:=msoShapeChevron, Left:=50, top:=topp, Width:=200, Height:=høgde)
.Name = r.Cells(i, 1)
farge = fargekart((i - 1) Mod UBound(fargekart))
.Fill.ForeColor.RGB = RGB(farge Mod 256, (farge \ 256) Mod 256, farge \ 65536)
For Each nd In .Nodes
Debug.Print nd.Left
Next nd
End With
topp = topp + høgde
Next i
End With
Debug.Print r.Address
End Sub
Honestly, I am unsure if this can be done at all, but even if it is impossible, it would be nice to get it confirmed :)
What you're looking for is .Nodes.SetPosition. Because it's relative positioning, this can be a challenge. You need to use the objects position elements to make sure the points are moving in relation to the shape.
With .AddShape(Type:=msoShapeChevron, Left:=50, Top:=topp, Width:=200, Height:=høgde)
.Name = r.Cells(i, 1)
.Nodes.SetPosition 2, .Left + .Width, .Top
.Nodes.SetPosition 4, .Left + .Width, .Top + .Height
First argument is the node index. Next is the x position, which we want all the way to the right of the graphic, so we add the shapes position left to the width of the shape. Last is the y position, first point we want in the topmost corner, so we use the shapes top. Last point, we add the height to the top position to bring to the bottom corner.
I believe it would be more simple drawing this as free form using Shapes.BuildFreeform Method and then converting to shape using FreeformBuilder.ConvertToShape Method.
Example:
Sub drawEntryArrow()
Dim x1 As Single, y1 As Single, w As Single, h As Single
Dim oShape As Shape
x1 = 10
y1 = 10
w = 200
h = 200
With ActiveSheet.Shapes.BuildFreeform(msoEditingAuto, x1, y1)
.AddNodes msoSegmentLine, msoEditingAuto, x1 + w, y1
.AddNodes msoSegmentLine, msoEditingAuto, x1 + w, y1 + h
.AddNodes msoSegmentLine, msoEditingAuto, x1, y1 + h
.AddNodes msoSegmentLine, msoEditingAuto, x1 + w / 2, y1 + h / 2
.AddNodes msoSegmentLine, msoEditingAuto, x1, y1
Set oShape = .ConvertToShape
End With
End Sub
If you just want to get rid of the point at the right, you can simply delete the node (nodes of a chevron are counted clockwise starting at the top left):
.Nodes.Delete 3
To get access to all nodes with the nodes-property of a shape, however, as long as you deal with a standard shape type, you can't access the coordinates.
When you use the "edit points", a shape changes its type to msoShapeNotPrimitive - but I couldn't figure out how to do this using VBA.
UPDATE
Played around a bit (because I'm curious) - just as an example if someone wants to change a shape manually:
' First change Shape Type:
' WILL NOT WORK: sh.AutoShapeType = msoShapeNotPrimitive
' Instead, add a node and remove it immediately. This changes the shape type.
.Nodes.Insert c, msoSegmentLine, msoEditingCorner, 100, 100
.Nodes.Delete c + 1
' Now access the x-coordinate of node 2 and the y-coordinate of node 3
' (note that we cannot access the coordinates directly)
Dim pointsArray() As Single, x As Single, y As Single
pointsArray = .Nodes(2).Points
x = pointsArray(1, 1)
pointsArray = .Nodes(3).Points
y = pointsArray(1, 2)
' Now change the x-value of node 3
sh.Nodes.SetPosition 3, x, y
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
I'm working with a MSchart and I'm trying to figure out how to show the x-axis value based on the mouse's position in the graph. It only shows when the mouse is on a datapoint. The y-axis is scaled linearly and works as it should.
The x-axis however doesn't since it is logarithmic and gives me results this:
(0 = 0, 10 = 1, 100 = 2, 1000 = 3)
Where x = 10, it gives me a returned value of 1, where x = 100, it gives me a returned value of 2, and etc.
dim position = e.Location
dim result = myChart.hitTest(position.x, position.y)
etoolTip.active = true
if(result.ChartElementType = DataVisualization.Charting.ChartElementType.datapoint)
dim x = result.ChartArea.AxisX.PixelPositionToValue(position.x)
dim y = result.chartarea.axisy.pixelPositionToValue(position.y)
etoolTip.SetToolTip(phaseNoiseChart, "X:"&x &"Y:"&y)
else
etoolTip.active = false
End If
How do I get the x-axis's true position based on the mouse's position for an axis that is logarithmic?
since the code belongs to mouse move event
e.X will give you the x co-ordinate
e.Y will give you the y co-ordinate
I clearly didn't understand what those numbers meant until I realized what the answer was telling me. The way I turn it back into actual coordinates is by 10^x.
dim x = result.ChartArea.AxisX.PixelPositionToValue(position.x)
x = 10^x
dim y = result.chartarea.axisy.pixelPositionToValue(position.y)
etoolTip.SetToolTip(phaseNoiseChart, "X:"&x & "Y:"&y)