I am a beginner in Powershell scripting and facing this problem:
I generated a set of tables in a Word document.
At the end I like to align for each table the texts in all cells of the second column vertically centered. I tried to use a code structure like:
$document.Tables | ForEach-Object {...}
However I find no way to get the hands on the individual column of each table to align the texts.
What would be a possible way?
Found no answer so far. So I ended up with the following:
$word = New-Object -ComObject word.application
$document = $word.documents.open($wordTemplatePath)
...
For ($i = 1; $i -le $document.Tables.Count; $i++) {
$a = $document.Tables.Item($i).Columns.Item(2).Select()
$objSelection = $word.Selection
$objSelection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
$objSelection.Cells.VerticalAlignment = 1
}
Works fine.
To justify the whole table you can use:
$table.Range.ParagraphFormat.Alignment=1
To do just a cell:
$table.Cell(1,1).Range.ParagraphFormat.Alignment=1
Other values are 0 left (default) and 2 right
A combination of these should have your table looking perfect.
Related
I am trying to increase the level of automation within my day-to-day work, part of which involves adding a line to the end of a table within a report that contains largely the same information, with a few cells changed (new dates).
I have a little experience with VB and C++, but I am very much an amateur when it comes to PowerShell, which seems to be the go-to for task automation.
I have a couple of PowerShell scripts that search through the body of the report and change text, but the last part of the report is a record, and needs appending as opposed to amending.
How would I go about this?
I have tried mangling a few bits of PowerShell code I've found online, to no avail. I have gotten as far as selecting a row in the correct table, but I have no idea how I might then select the last row, copy this and insert it beneath as a new row at the bottom of the table:
$objWord = New-Object -ComObject word.application
$objWord.Visible = $True
$objWord.Documents.Open("FILEPATH")
$FindText = "KEYTEXT"
$objWord.Selection.Find.Execute($FindText)
$objWord.Selection.SelectRow()
Here's a lengthy example with explanations that does what you're looking for:
# open document
$objWord = New-Object -ComObject word.application
$objWord.Visible = $True
$doc = $objWord.Documents.Open("C:\temp\temp.docx")
# search for row
$FindText = "Value2"
$result = $objWord.Selection.Find.Execute($FindText)
$objWord.Selection.SelectRow()
# copy the ranges from searched row
$table = $objWord.Selection.Tables[1]
$copiedCells = $objWord.Selection.Cells | select columnindex,rowindex
# add row at the end of table
$table.Rows[$table.Rows.Count].Select()
$objWord.Selection.InsertRowsBelow(1)
# insert copied text into each column of last row
foreach ($cell in $copiedCells) {
# copy value from cell in copied row
$copiedText = $table.Cell($cell.rowindex, $cell.columnindex).Range.Text
# remove last 2 characters (paragraph and end-of-cell)
$TrimmedText = $copiedText.Remove($copiedText.Length - 2)
# set value for cell in last row
$table.Cell($table.Rows.Count,$cell.columnindex).Range.Text = $TrimmedText
}
I'm trying to automate adding new tables to a Word document using Powershell.
I wrote a Powershell script that is meant for adding summary tables based on a whole document in a proper location. It gathers the information from the file contents and then, in the selected ranges, creates a new summary tables. The table is always inserted at the end of the range (which is a chapter in the document). The range is based on the list headers. However, while adding a new table to the selected range, I cannot force Word to leave the next header which is chosen as the end of the range. It gets deleted.
For example: I'm having chapters from 1.1 to 1.10 in my file and I'm choosing to add a new table at the end of the chapter 1.1, right before the chapter 1.2. A whole chapter 1.2. header is deleted and the chapter 1.3 is now labeled as 1.2.
I tried substracting various numbers from the Range.End property, following information in the Microsoft documentation (https://learn.microsoft.com/en-us/office/vba/api/word.range.end), however is doesn't seem to give any results.
The code (shortcut):
Add-Type -AssemblyName Microsoft.Office.Interop.Word
$word = New-Object -ComObject Word.application
$report = $word.Documents.Open("C:\file.docx")
#information gathering here
#find the right location and add a new table
$start = $report.Paragraphs | ? {$_.Range.ListFormat.ListString -eq '1.1'} | % {$_.Range}
$end = $report.Paragraphs | ? {$_.Range.ListFormat.ListString -eq '1.2'} | % {$_.Range}
$first_table = $report.Range($start.Start, $end.Start).Tables.Add($end, 24, 4, [ref]$DefaultTableBehavior::wdWord9TableBehavior, [ref]$AutoFitBehavior::wdAutoFitFixed)
#continue with filling up the table
Part of the problem is that if you have a sequence of empty auto-numbered paragraphs, inserting a table into one of them will mean that subsequent paragraphs will be placed inside the table.
Also, if your 1.1 section can contain material, AFAICS your $start will contain the range of its first paragraph, which isn't very useful - all you really need is that location of the paragraph you want to insert before.
As an alternative, I suggest that you start by inserting a paragraph mark immediately before the 1.2 heading, then insert the table.
e.g. like this:
#$start = $report.Paragraphs | ? {$_.Range.ListFormat.ListString -eq '1.1'} | % {$_.Range}
$end = $report.Paragraphs | ? {$_.Range.ListFormat.ListString -eq '1.2'} | % {$_.Range}
$place = $report.Range($end.Start - 1, $end.Start-1)
$place.InsertParagraph()
$place = $report.Range($end.Start - 1, $end.Start-1)
$first_table = $place.Tables.Add($place, 24, 4, [ref]$DefaultTableBehavior::wdWord9TableBehavior, [ref]$AutoFitBehavior::wdAutoFitFixed)
If you don't want that extra paragraph mark, you can probably delete it, and if you really want, you could use
$report.Range($end.Start-1, $end.Start).Text = ""
after the table insertion.
I don't seem to find quite a bit of examples of PowerShell and Microsoft Word. I've seen plenty of how to post a page number in a footer, but I don't quite grasp the PowerShell select method or object. An example of how to count up pages in any particular set of documents was also reviewed.
I've dug through quite a few books and only one of them really had anything to do with PowerShell and MS Word. If anything only a few trivial Excel examples or how to create a word document was given. I also noticed that Office 365 is offered as a focus point of one book and even an online script building resource, but nothing like that I could find on Office 2013 and prior.
This is the script that I'm working with now which isn't really much to look at.
$objWord = New-Object -ComObject Word.Application;
$objWord.Visible = $false;
$objWord.DisplayAlerts = "wdAlertsNone";
# Create the selection object
$Selection = $objWord.Selection;
#$document = $objWord.documents.open("C:\Path\To\Word\Document\file.docx");
$hyperlinks = #($document.Hyperlinks);
#loop through all links in the word document
$hyperlinks | ForEach {
if($_.Address -ne $null)
{
# The character number where the hyperlink text starts
$startCharNumber = $_.Range.Start;
# The character number where the hyperlink text ends
$endCharNumber = $_.Range.End;
# Here is where to calculate which page number the $startCharNumber is found on. How exactly to do this?
# For viewing purposes only. To be used to create a report or index.
Write-Host "Text To Display: " $_.TextToDisplay " URL: " $_.Address " Page Num: " ;
}
}
$objWord.quit();
You can use Information(wdActiveEndPageNumber) to get the page containing the selection.
$word = [System.Runtime.InteropServices.Marshal]::GetActiveObject('Word.Application')
$wdActiveEndPageNumber = 3
$doc = $word.ActiveDocument
foreach ($h in $doc.Hyperlinks) {
$page = $h.Range.Information($wdActiveEndPageNumber)
echo "Page $page : $($h.Address)"
}
Edited following #bibadia's comment.
I'm currently trying to create a calendar in powerpoint using powershell. All I want to do is insert a table into a powerpoint slide. This table is representing the month of January, it contains the days of the week etc.
I did some research and came across this.
This is VB script, so i tried to "create its equivalent" in powershell:
EDIT3: I was finally able to copy my table from Excel and paste it into my powerpoint slide using this code:
#Create an instance of Excel.
$xl=New-Object -ComObject "Excel.Application"
$xl.Visible = $True
#Open the Excel file containing the table.
$wb = $xl.workbooks.open("C:\January.xls")
$ws = $wb.ActiveSheet
#Select the table.
$range = $ws.range("A1:G7")
$range.select()
#Copy the table to the clipboard.
$range.copyPicture()
#Create an instance of Powerpoint.
$objPPT = New-Object -ComObject "Powerpoint.Application"
$objPPT.Visible ='Msotrue'
#Add a slide to the presentation.
$project = $objPPT.Presentations.Add()
$slide = $project.Slides.Add(1, 1)
#Paste the table into the slide.
$shape = $slide.Shapes.Paste()
#Position the table.
$shape.Left = 50
$shape.Top = 150
$shape.Width = 300
$shape.Height = 168
Thanks to those who have helped me here and on #powershell
I saw your question in the channel.
This worked for me:
$presentation = $ppt.Presentations.Open($ifile)
$sl = $presentation.Slides.Add(1, $ppLayoutBlank)
$shape = $sl.shapes.paste()
I think you can use this:
# Optionally, make sure you're on the last slide:
$ppt.ActiveWindow.View.GotoSlide( $ppt.ActivePresentation.Slides.Count )
# Specify the
$ppt.ActiveWindow.View.PasteSpecial( "ppPasteOLEObject", "msoFalse", "", 0, "", "msoFalse")
See the
MSDN Interop Docs
and thanks to this example:
Paste Excel Chart into Powerpoint using VBA
I have a word document (2003). I am using Powershell to parse the content of the document.
The document contains a few lines of text at the top, a dozen tables with differing number of columns and then some more text.
I expect to be able to read the document as something like the below:
Read document (make necessary objects etc)
Get each line of text
If not part of a table, process as text and Write-Output
else
If part of a table
Get table number (by order) and parse output based on columns
end if
Below is the powershell script that I have begun to write:
$objWord = New-Object -Com Word.Application
$objWord.Visible = $false
$objDocument = $objWord.Documents.Open($filename)
$paras = $objDocument.Paragraphs
foreach ($para in $paras)
{
Write-Output $para.Range.Text
}
I am not sure if Paragraphs is what I want. Is there anything more suitable for my purpose?
All I am getting now is the entire content of the document. How do I control what I get. Like I want to get a line, be able to determine if it is part of a table or not and take an action based on what number table it is.
You can enumerate the tables in a Word document via the Tables collection. The Rows and Columns properties will allow you to determine the number of rows/columns in a given table. Individual cells can be accessed via the Cell object.
Example that will print the value of the cell in the last row and last column of each table in the document:
$wd = New-Object -ComObject Word.Application
$wd.Visible = $true
$doc = $wd.Documents.Open($filename)
$doc.Tables | ForEach-Object {
$_.Cell($_.Rows.Count, $_.Columns.Count).Range.Text
}