Word-Vba: InlineShapes.Addpicture image sits higher than its previous image - vba

Sub GetPictures()
Dim sPic As String
Dim sPath As String
Dim sCount As Long
sPath = "G:\Images\Alphabet_Lower_Case\"
sPic = Dir(sPath & "*.jpg")
Do While sPic <> ""
Selection.InlineShapes.AddPicture _
FileName:=sPath & sPic, _
LinkToFile:=False, SaveWithDocument:=True
With Selection
With .Borders(wdBorderLeft)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth300pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderRight)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth300pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderTop)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth300pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderBottom)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth300pt
.Color = wdColorAutomatic
End With
.Borders.Shadow = False
End With
Selection.Paragraphs.Format.Alignment = wdAlignParagraphCenter
sPic = Dir
With Selection
.Collapse Direction:=wdCollapseEnd
.TypeParagraph
End With
Loop
With ThisDocument.PageSetup.TextColumns
.SetCount NumColumns:=2
End With
Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Cut
End Sub
'Any idea on how to lower the image on the right hand side to the same level as the one of the left (previous)? E.g. b is sitting higher than it should be and is occluding the border.
All images have the same 600x600 dimension.
See the following output for clarification.
a&b
Here's a screen capture and the grid behind 'b' shows the shift.
preview

Related

Word Macro - set orientation of selected page

I'm trying to make a macro where users can select a table within a document and switch the orientation of the specific page it's on to landscape. I've tried both recording doing the action and writing the macro myself but it never seems to work properly. This is as close as I've gotten but it makes the page the table is on and everything before it landscape.
Sub TableLandscape()
'
' TableLandscape Macro
'
'
'Selection.Collapse Direction:=wdCollapseEnd
'Selection.InsertBreak Type:=wdSectionBreakContinuous
'ActiveDocument.Range(Start:=Selection.Start, End:=Selection.Start).Collapse Direction:=wdCollapseStart
'Selection.InsertBreak _
Type:=wdSectionBreakNextPage
Selection.Start = Selection.Start + 1
ActiveDocument.Range(Start:=Selection.End, End:=Selection.End).InsertBreak _
Type:=wdSectionBreakNextPage
With Selection.PageSetup
.LineNumbering.Active = False
.Orientation = wdOrientLandscape
.TopMargin = InchesToPoints(1)
.BottomMargin = InchesToPoints(1)
.LeftMargin = InchesToPoints(1)
.RightMargin = InchesToPoints(1)
.Gutter = InchesToPoints(0)
.HeaderDistance = InchesToPoints(0.6)
.FooterDistance = InchesToPoints(0.5)
.PageWidth = InchesToPoints(11)
.PageHeight = InchesToPoints(8.5)
.FirstPageTray = wdPrinterDefaultBin
.OtherPagesTray = wdPrinterDefaultBin
.SectionStart = wdSectionContinuous
.OddAndEvenPagesHeaderFooter = False
.DifferentFirstPageHeaderFooter = False
.VerticalAlignment = wdAlignVerticalTop
.SuppressEndnotes = False
.MirrorMargins = False
.TwoPagesOnOne = False
.BookFoldPrinting = False
.BookFoldRevPrinting = False
.BookFoldPrintingSheets = 1
.GutterPos = wdGutterPosLeft
End With
'ActiveDocument.Range(Start:=Selection.End, End:=Selection.End).InsertBreak _
'Type:=wdSectionBreakNextPage
End Sub
Here's how to do that:
Sub RotatePage()
Dim TableRange As Range, TableStart As Range, TableEnd As Range
Set TableRange = Selection.Tables(1).Range
Set TableStart = TableRange.Duplicate
With TableStart
.SetRange Start:=TableStart.Start - 1, End:=TableStart.End
.Collapse Direction:=wdCollapseStart
.InsertBreak Type:=wdSectionBreakNextPage
End With
Set TableEnd = TableRange.Duplicate
With TableEnd
.SetRange Start:=TableEnd.Start, End:=TableEnd.End + 1
.Collapse Direction:=wdCollapseEnd
.InsertBreak Type:=wdSectionBreakNextPage
End With
TableRange.PageSetup.Orientation = wdOrientLandscape
End Sub

how to use inlineshape addpicture function

I wrote the code below to add an image to header. I placed the .png file in a network file. The following code works in my PC, but not in a different PC which also has access to the same network drive. It does import the image into the header but throws an error at the (.addpicture) line as shown in attached image. Wondering why the same code which works in one computer is bombing in the other one. Appreciate any directions. Thanks
Private Sub AddHeaderToRange(rng As Word.Range)
Dim sFindText As String
With rng
.Tables.Add Range:=rng, NumRows:=1, NumColumns:=2 'DefaultTableBehavior:=wdWord8TableBehavior,
AutoFitBehavior:=wdAutoFitFixed
With .Tables(1)
.PreferredWidth = Application.InchesToPoints(7)
.Rows.Alignment = wdAlignRowCenter
.Borders.InsideLineStyle = wdLineStyleNone
.Borders.OutsideLineStyle = wdLineStyleSingle
.Rows.SetLeftIndent LeftIndent:=0, RulerStyle:=wdAdjustNone
.Columns(1).SetWidth ColumnWidth:=200, RulerStyle:=wdAdjustNone
.Columns(2).SetWidth ColumnWidth:=225, RulerStyle:=wdAdjustNone
.cell(1, 1).Range.InlineShapes.AddPicture
Filename:="\\srv2\gv1\eng\strss\Pics\Testlogo.png", LinkToFile:=False,
SaveWithDocument:=True
.cell(1, 2).Range.Font.name = "Arial"
.cell(1, 2).Range.Font.Size = 12
.cell(1, 1).Range.ParagraphFormat.Alignment = wdAlignParagraphLeft
.cell(1, 2).Range.Text = Sheets("Start").Range("P9").Value & " " &
Sheets("Start").Range("P10").Value
sFindText = Sheets("Start").Range("P9").Value & " " & Sheets("Start").Range("P10").Value
.cell(1, 2).Range.ParagraphFormat.Alignment = wdAlignParagraphRight
For Each r In .Rows
r.Borders(wdBorderLeft) = wdLineStyleNone
r.Borders(wdBorderRight) = wdLineStyleNone
r.Borders(wdBorderTop) = wdLineStyleNone
Next
.Rows(1).Cells.VerticalAlignment = wdAlignVerticalBottom
.AutoFitBehavior (wdAutoFitWindow)
'.Rows.WrapAroundText = True
End With
.ParagraphFormat.SpaceBefore = 0
.ParagraphFormat.SpaceAfter = 0
End With
With rng.Find
.Text = sFindText
If .Execute(Forward:=True) = True Then
rng.Fields.Add rng, _
wdFieldEmpty, _
"DocProperty TitleReference", PreserveFormatting:=True
End If
End With
Exit Sub
eh:
Call Errorhandler("AddHeaderToRange", Err)
End Sub
The syntax is:
Activedocument.Tables(1).Rows(1).Cells(1).Range.InlineShapes.AddPicture
After you fix that, you'll also get errors for the following lines that use .cell instead of Rows(1).Cells(1).

Run-Time Error '462'

I am trying to run a macro from excel that will open up an existing word document, populate the fields from excel to word via content controls, and paste/format a table into the word document at a certain location. About 20% of the time, I'll get this Run Time Error 462 stating "The remote Server Machine Does Not Exist or is Unavailable". I will provide the code and the section where is usually gets stuck at as everything after works 100% of the time. Please help on this.
Public Sub Agreement()
With Sheets("Price List Table")
.ListObjects(1).Name = "Table1"
End With
Dim tbl As Excel.Range
Dim wrdApp
Dim wrdDoc
Dim WordTable As Word.Table
Dim c As Integer
Set tbl = ThisWorkbook.Worksheets(Sheet2.Name).ListObjects("Table1").Range
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = False
Set wrdDoc = wrdApp.Documents.Open("C:\Users\Documents\Example")
With wrdDoc
tbl.Copy
wrdApp.Selection.Find.Text = "This is the section for the table to be pasted below it."
wrdApp.Selection.Find.Execute
wrdApp.Selection.MoveDown Unit:=wdLine, Count:=5, Extend:=wdMove
wrdApp.Selection.PasteExcelTable False, False, False
Dim objTable As Object
For Each objTable In ActiveDocument.Tables ' (This is where the error occurs)
objTable.AutoFitBehavior (wdAutoFitWindow)
objTable.AllowAutoFit = True
Next
wrdApp.Selection.GoTo wdGoToPage, wdGoToAbsolute, 1
wrdApp.Selection.GoTo What:=wdGoToTable, Which:=GoToNext
wrdApp.Selection.GoTo What:=wdGoToTable, Which:=GoToNext
wrdApp.Selection.GoTo What:=wdGoToTable, Which:=GoToNext
wrdApp.Selection.Tables(1).Select
With wrdApp.Selection.Borders(wdBorderTop)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
With wrdApp.Selection.Borders(wdBorderLeft)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
With wrdApp.Selection.Borders(wdBorderBottom)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
With wrdApp.Selection.Borders(wdBorderRight)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
With wrdApp.Selection.Borders(wdBorderHorizontal)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
With wrdApp.Selection.Borders(wdBorderVertical)
.LineStyle = Options.DefaultBorderLineStyle
.LineWidth = Options.DefaultBorderLineWidth
.Color = Options.DefaultBorderColor
End With
wrdApp.Selection.Tables(1).Columns(3).Select
wrdApp.Selection.ParagraphFormat.Alignment = wdAlignParagraphRight
wrdApp.Selection.Tables(1).Columns(4).Select
wrdApp.Selection.ParagraphFormat.Alignment = wdAlignParagraphRight

My Word macro doesn't find the second word

I want to create a VBA script in Microsoft Word to find inside a txt file if exist some line with ":" character. If this is true, I want to get this line, split it and insert this information in a table that is in main file. To this objetive, I want to go through all found lines to get this information.
For this, I have this code:
Dim arrNames
Dim cont As Integer
cont = 0
strPath = ActiveDocument.name
Documents.Open path & "Mails.txt"
strPath2 = ActiveDocument.name
With Selection.Find
.Text = ":"
Do While .Execute(Forward:=True, Format:=True) = True
Selection.Find.Execute FindText:=(":")
Selection.Expand wdLine
arrNames = Split(Selection.Text, ":")
Documents(strPath).Activate
If cont = 0 Then
Call gestOSINT("Pwd")
Selection.Find.Execute FindText:=("[Pwd]")
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:= _
3, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed
With Selection.Tables(1)
If .Style <> "Tabla con cuadrícula" Then
.Style = "Tabla con cuadrícula"
End If
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
.ApplyStyleRowBands = True
.ApplyStyleColumnBands = False
End With
Set tblNew = Selection.Tables(1)
tblNew.Style = "Tabla de lista 1 clara - Énfasis 1"
Selection.TypeText Text:="Correo electrónico"
Selection.MoveRight Unit:=wdCell
Selection.TypeText Text:="Tipo de filtrado"
Selection.MoveRight Unit:=wdCell
Selection.TypeText Text:="Plataforma"
End If
Set rowNew = tblNew.Rows.Add
rowNew.Cells(1).Range.Text = arrNames(0)
rowNew.Cells(2).Range.Text = arrNames(1)
rowNew.Cells(3).Range.Text = arrNames(2)
cont = cont + 1
Documents(strPath2).Activate
Selection.Text = arrNames(0) & vbCrLf
Selection.MoveDown Unit:=wdLine, Count:=1
Selection.Collapse wdCollapseEnd
Loop
End With
Documents(strPath2).Activate
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
Documents(strPath).Activate
If cont = 0 Then
pwdMails = False
Else
pwdMails = True
End If
And Mails.txt file contain the following:
mail#mail.com
mail2#mail.com
mail3#mail.com:word1:word2
mail4#mail.com
mail5#mail.com:word3:word4
The first line which contain ":", line 3 in Mails.txt, was found but the second line, line 5 in Mails.txt, wasn't found.
Why occur this? How can I fix it?
Here is a version that reads the file via FileSystemObject and avoids using Selection. PLease note that I commented out lines that do not work for me (style names, custom functions).
Also: you are applying two styles to the table, first one then the other. Please pick one. ;-)
Const ForReading = 1
Dim arrNames
Dim cont As Integer
Dim fso, MyFile, FileName, TextLine, tblNew As Table, newRow As Row
Set fso = CreateObject("Scripting.FileSystemObject")
cont = 0
If cont = 0 Then
'Call gestOSINT("Pwd")
'Selection.Find.Execute FindText:=("[Pwd]")
Set tblNew = ActiveDocument.Tables.Add(Range:=Selection.Range, NumRows:=1, NumColumns:= _
3, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed)
With tblNew
' If .Style <> "Tabla con cuadrícula" Then
' .Style = "Tabla con cuadrícula"
' End If
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
.ApplyStyleRowBands = True
.ApplyStyleColumnBands = False
' .Style = "Tabla de lista 1 clara - Énfasis 1"
End With
With tblNew.Rows(1)
.Cells(1).Range.text = "Correo electrónico"
.Cells(2).Range.text = "Tipo de filtrado"
.Cells(3).Range.text = "Plataforma"
End With
End If
FileName = path & "Mails.txt"
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
TextLine = MyFile.ReadLine
If InStr(1, TextLine, ":") > 0 Then
arrNames = VBA.split(TextLine, ":")
Set rowNew = tblNew.Rows.Add
rowNew.Cells(1).Range.text = arrNames(0)
rowNew.Cells(2).Range.text = arrNames(1)
rowNew.Cells(3).Range.text = arrNames(2)
End If
Loop
MyFile.Close
If cont = 0 Then
pwdMails = False
Else
pwdMails = True
End If

How to merge two cells in excel(both with contents) keeping the formatting intact using VBA?

I have two cells A1 and A2. I want to merge them and store in A3 keeping the formatting intact. I was able to use the below code to do this. But there is a huge performance issue. Can any one suggest a better solution? Is there a simpler way to do this?
Sub Merge_Cells(rngFrom1 As Range, rngFrom2 As Range, rngTo As Range)
Dim iOS As Integer
Dim lenFrom1 As Integer
Dim lenFrom2 As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlManual
lenFrom1 = rngFrom1.Characters.Count
lenFrom2 = rngFrom2.Characters.Count
rngTo.Value = rngFrom1.Text & rngFrom2.Text
For iOS = 1 To lenFrom1
With rngTo.Characters(iOS, 1).Font
.Bold = rngFrom1.Characters(iOS, 1).Font.Bold
.Size = 9 'rngFrom1.Characters(iOS, 1).Font.Size
.Color = rngFrom1.Characters(iOS, 1).Font.Color
.Italic = rngFrom1.Characters(iOS, 1).Font.Italic
.Strikethrough = rngFrom1.Characters(iOS, 1).Font.Strikethrough
.Underline = rngFrom1.Characters(iOS, 1).Font.Underline
End With
Next iOS
For iOS = 1 To lenFrom2
With rngTo.Characters(lenFrom1 + iOS, 1).Font
.Name = rngFrom2.Characters(iOS, 1).Font.Name
.Bold = rngFrom2.Characters(iOS, 1).Font.Bold
.Size = 9 'rngFrom2.Characters(iOS, 1).Font.Size
.Color = rngFrom2.Characters(iOS, 1).Font.Color
.Italic = rngFrom2.Characters(iOS, 1).Font.Italic
.Strikethrough = rngFrom2.Characters(iOS, 1).Font.Strikethrough
.Underline = rngFrom2.Characters(iOS, 1).Font.Underline
End With
Next iOS
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Three suggestions:
1. Set a character's properties only if you need to
It's possible (I don't know for sure) that setting a character's properties is more expensive than getting a character's properties. If the cost differential is high enough then it makes sense to check the property to see if it needs to be set, before you actually set it.
So, for example, your code would become:
Sub Merge_Cells2(rngFrom1 As Range, rngFrom2 As Range, rngTo As Range)
Dim iOS As Integer
Dim lenFrom1 As Integer
Dim lenFrom2 As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlManual
lenFrom1 = rngFrom1.Characters.Count
lenFrom2 = rngFrom2.Characters.Count
rngTo.Value = rngFrom1.Text & rngFrom2.Text
For iOS = 1 To lenFrom1
With rngTo.Characters(iOS, 1).Font
If .Bold <> rngFrom1.Characters(iOS, 1).Font.Bold Then .Bold = rngFrom1.Characters(iOS, 1).Font.Bold
If .Size <> 9 Then .Size = 9
If .Color <> rngFrom1.Characters(iOS, 1).Font.Color Then .Color = rngFrom1.Characters(iOS, 1).Font.Color
If .Italic <> rngFrom1.Characters(iOS, 1).Font.Italic Then .Italic = rngFrom1.Characters(iOS, 1).Font.Italic
If .StrikeThrough <> rngFrom1.Characters(iOS, 1).Font.StrikeThrough Then .StrikeThrough = rngFrom1.Characters(iOS, 1).Font.StrikeThrough
If .Underline <> rngFrom1.Characters(iOS, 1).Font.Underline Then .Underline = rngFrom1.Characters(iOS, 1).Font.Underline
End With
Next iOS
For iOS = 1 To lenFrom2
With rngTo.Characters(lenFrom1 + iOS, 1).Font
If .Bold <> rngFrom2.Characters(iOS, 1).Font.Bold Then .Bold = rngFrom2.Characters(iOS, 1).Font.Bold
If .Size <> 9 Then .Size = 9
If .Color <> rngFrom2.Characters(iOS, 1).Font.Color Then .Color = rngFrom2.Characters(iOS, 1).Font.Color
If .Italic <> rngFrom2.Characters(iOS, 1).Font.Italic Then .Italic = rngFrom2.Characters(iOS, 1).Font.Italic
If .StrikeThrough <> rngFrom2.Characters(iOS, 1).Font.StrikeThrough Then .StrikeThrough = rngFrom2.Characters(iOS, 1).Font.StrikeThrough
If .Underline <> rngFrom2.Characters(iOS, 1).Font.Underline Then .Underline = rngFrom2.Characters(iOS, 1).Font.Underline
End With
Next iOS
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
As I mentioned, I don't really know if this is a win, and the degree of advantage might vary from property to property. Maybe someone more knowledgable than I can comment. Or you can just try it out and see if it helps.
2. Set size all at once
Since you seem to be setting size to 9 all the time, I'd suggest setting size to 9 for the entire cell all at once, a rather than character by character. Then again, maybe you commented it out because you intend to restore size copying, and if so, this suggestion won't work.
3. Exploit sparseness
If the formatting is sparse, then you can check long runs of characters (or entire cells) for a particular property before you do anything. For example, if many cells have no bolding, check each cell before doing anything else. You might not have to do anything at all about bolding. My Excel returns Null when a property isn't uniform across a run of characters. (ymmv) If you get a Null, then you know you'll have to slice that character run more finely.
4. Addendum
#DavidZemens' suggestion about font size led me to this idea, which pays off only if Set is more expensive than Get for character properties. One could by inspection formulate a guess of the most common character style (font, size, color, bold, etc.), define that by hand as a cell style and apply it to the target range by hand. That would minimize the number of If's that trigger property sets.
-hth