Get select amount of tables from a Word doc

Hello,
Brand new to the forum and glad I found it.
The goal of my script is to prompt the user to select a word document and ask the user to specify how many tables in the word document would you like to export (it will be exported to csv). I’m asking the user how many tables, because it could vary per document.
So I prompt the user:

# Display the menu and get the user's choice
$objDocument = $objWord.Documents.Open($filename)
$objWord     = New-Object -Com Word.Application
$choice = Read-Host "Enter the number of tables in the word document that need to be imported"

But how to I have the script grab just the number of tables that the user input? I.E., if I specify 3, the script will grab the first 3 tables from the word doc and export them to CSV.

Thank you in advance!

Hi, welcome to the forum :wave:

Firstly, when posting code in the forum, please can you use the preformatted text </> button. It really helps us with readability, and copying and pasting your code (we don’t have to faff about replacing curly quote marks to get things working). If you can’t see the </> in your toolbar, you will find it under the gear icon.

How to format code on PowerShell.org

Your friend here will be Get-Member.

If you run

$objDocument | Get-Member

You’ll see it has a property Tables which contains all the table definitions. It’s not an array so you can’t use the index, but if you want the first 3 tables, you could do:

$TablesToExport = $objDocument.Tables | Select-Object -First 3

By the way, unlike VBScript, it’s not a PowerShell convention to include the type in the variable name.
$Document and $Word are perfectly acceptable.

Thank you for the n00b tips. I clearly just joined and posted my question without reading the guidelines. I appreciate the direction.

I’ve updated my code:

#####################################################################################
### This function opens a Windows Dialog Box for the selection of the source file ###
#####################################################################################

Write-Output "################################################"
Write-Output " "
Write-Output "Select the source file."
Write-Output "The starting directory is  C:\."
Write-Output " "
Write-Output "################################################"

Function Get-FileName($initialDirectory)
{
    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
   
    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.initialDirectory = $initialDirectory
    $OpenFileDialog.filter = "docx (*.docx)| *.docx"
    $OpenFileDialog.ShowDialog() | Out-Null
    $OpenFileDialog.filename
}
$inputfile = Get-FileName "C:\"

$Word     = New-Object -Com Word.Application
$Document = $Word.Documents.Open($inputfile)

#######################
### End of function ###

#############################################################################
### This function lists a menu for the user to choose the number of tables###
### in the word document that need to be imported ###########################
#############################################################################

# Display the menu and get the user's choice
$choice = Read-Host "Enter the number of tables in the word document that need to be imported"

#######################
### End of function ###

$TablesToExport = $Document.Tables | Select-Object -First $choice

$TablesToExport | Export-csv Medwell.csv


$Document.Close()
$Word.Quit()
# Stop Winword Process
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Document)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Yes the CSV output file looks bizzare:

#TYPE System.__ComObject#{00020951-0000-0000-c000-000000000046}
"Range","Application","Creator","Parent","Columns","Rows","Borders","Shading","Uniform","AutoFormatType","Tables","NestingLevel","AllowPageBreaks","AllowAutoFit","PreferredWidth","PreferredWidthType","TopPadding","BottomPadding","LeftPadding","RightPadding","Spacing","TableDirection","ID","Style","ApplyStyleHeadingRows","ApplyStyleLastRow","ApplyStyleFirstColumn","ApplyStyleLastColumn","ApplyStyleRowBands","ApplyStyleColumnBands","Title","Descr"
"System.__ComObject","Microsoft.Office.Interop.Word.ApplicationClass","1297307460","Microsoft.Office.Interop.Word.DocumentClass","System.__ComObject","System.__ComObject","System.__ComObject","System.__ComObject","True","1","System.__ComObject","1","True","True","9999999","2","0","0","5.4","5.4","0","1",,"System.__ComObject","True","False","True","False","True","False",,
"System.__ComObject","Microsoft.Office.Interop.Word.ApplicationClass","1297307460","Microsoft.Office.Interop.Word.DocumentClass","System.__ComObject","System.__ComObject","System.__ComObject","System.__ComObject","True","1","System.__ComObject","1","True","True","9999999","2","0","0","5.4","5.4","0","1",,"System.__ComObject","True","False","True","False","True","False",,
"System.__ComObject","Microsoft.Office.Interop.Word.ApplicationClass","1297307460","Microsoft.Office.Interop.Word.DocumentClass","System.__ComObject","System.__ComObject","System.__ComObject","System.__ComObject","True","1","System.__ComObject","1","True","True","9999999","2","0","0","5.4","5.4","0","1",,"System.__ComObject","True","False","True","False","True","False",,

I wondered what your plan was for exporting the data :slight_smile:. There are no methods in the COM object for exporting tables. I don’t think you can even do it in Word unless it’s buried deep in the menus somewhere.

You might have some luck with the ConvertToText() method although I expect you’ll have problems if the data is complex or already has commas or something else you want to use as a separator.

From a very quick test, I think your best bet will be to try the ImportExcel module and just grab the table from the clipboard.

Then you can do something like this:

$Word = New-Object -ComObject Word.Application
$Doc = $Word.Documents.Open('E:\Temp\testWord.docx')
$TableToExport = $Doc.Tables | Select-Object -First 1
$TableToExport.Range.Copy()
# Read-Clipboard is a command in the ImportExcel module.
Read-Clipboard | Export-Csv .\myTable.csv -NoTypeInformation

I hadn’t come across ImportExcel, thanks for that.

I was originally ‘borrowing’ methods from the script I found here. Powershell-MS Word docx table to csv

I simply couldn’t figure out how to alter it to export just the number of tables that a user may specify.

This is getting me there.

$objWord     = New-Object -Com Word.Application
$filename    = 'c:\blah.docx'
$outputfile  = 'c:\blah.csv'
$objDocument = $objWord.Documents.Open($filename)


# Display the menu and get the user's choice
$choice = Read-Host "Enter the number of tables in the word document that need to be imported"

$Tables = $objDocument.Tables | Select-Object -First $choice


foreach($Table in $Tables)
{
$TableCols = $Table.Columns.Count
$TableRows = $Table.Rows.Count
# this gets the list separator character your local Excel expects when double-clicking a CSV file
$delimiter = [cultureinfo]::CurrentCulture.TextInfo.ListSeparator



for($r = 1; $r -le $TableRows; $r++) {
    # capture an array of cell contents
    $content = for($c = 1; $c -le $TableCols; $c++) {
        # surround each value with quotes to prevent fields that contain the delimiter character would ruin the csv,
        # double any double-quotes the value may contain,
        # remove the control characters (0x0D 0x07) Word appends to the cell text
        # trim the resulting value from leading or trailing whitespace characters
        #'"{0}"' -f ($Table.Cell($r,$c).Range.Text -replace '"', '""' -replace '[\x00-\x1F\x7F]').Trim()
		($Table.Cell($r,$c).Range.Text -replace '[\x00-\x1F\x7F]').Trim()
    }
    # output this array joined with the delimiter, both on screen and to file
    $content -join $delimiter | Add-Content -Path $outputfile -PassThru
}
}
$objDocument.Close()
$objWord.Quit()
# Stop Winword Process
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objDocument)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()```

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.