# populate_tablebox.ps1 — create a new sheet with a populated TableBox on a QVW. # # IMPORTANT: use TableBox.AddField($fieldName) — NOT TableBoxProperties.Fields.Add() # (which fails on modern QV Document COM with "null-valued expression"). # # Usage: # powershell -File populate_tablebox.ps1 ` # -QvwPath "C:\path\to\app.qvw" ` # -SheetName "Cash Flow (v9)" ` # -Fields @("%ProdPODateKey","cf_category","cf_payment_date","cf_amount_ron","ext_supplier_code") # # The sheet is CREATED if it doesn't match `$SheetName` (case-insensitive substring). # A fresh TableBox is always created on the sheet. Existing TBs are NOT deleted — # pass -ReplaceExisting $true to remove old TBs on the sheet first. param( [Parameter(Mandatory=$true)][string]$QvwPath, [Parameter(Mandatory=$true)][string]$SheetName, [Parameter(Mandatory=$true)][string[]]$Fields, [bool]$ReplaceExisting = $false ) $ErrorActionPreference = "Continue" if (-not (Test-Path $QvwPath)) { throw "QVW not found: $QvwPath" } $qv = New-Object -ComObject QlikTech.QlikView $doc = $qv.OpenDoc($QvwPath, "", "") if (-not $doc) { throw "OpenDoc returned null for $QvwPath" } Start-Sleep -Seconds 2 # Find or create the sheet $targetSheet = $null $targetSheetId = $null for ($i=0; $i -lt $doc.NoOfSheets(); $i++) { $s = $doc.GetSheet($i) $sp = $s.GetProperties() $nm = $null try { $nm = $sp.Name } catch { try { $nm = $sp.Name.v } catch {} } if ($nm -and ($nm -like "*$SheetName*" -or $nm -eq $SheetName)) { $targetSheet = $s $targetSheetId = $sp.SheetId Write-Host "sheet exists: $nm (id=$targetSheetId)" break } } if (-not $targetSheet) { $targetSheet = $doc.CreateSheet() $sp = $targetSheet.GetProperties() try { $sp.Name = $SheetName } catch { try { $sp.Name.v = $SheetName } catch {} } $targetSheet.SetProperties($sp) $targetSheetId = $targetSheet.GetProperties().SheetId Write-Host "sheet created: $SheetName (id=$targetSheetId)" } # Optionally remove existing TBs on the sheet (reads -prj XML to find them) if ($ReplaceExisting) { $prjPath = [System.IO.Path]::GetDirectoryName($QvwPath) + "\" + [System.IO.Path]::GetFileNameWithoutExtension($QvwPath) + "-prj" $prjXml = Join-Path $prjPath "QlikViewProject.xml" if (Test-Path $prjXml) { $xml = [xml](Get-Content $prjXml) $sheetNode = $xml.PrjQlikViewProject.SHEETS.PrjSheetProperties | Where-Object { $_.SheetId -eq "Document\$targetSheetId" } if ($sheetNode) { foreach ($ch in $sheetNode.ChildObjects.PrjFrameParentDef) { if ($ch.ObjectId -like "Document\TB*") { $tbId = $ch.ObjectId.Replace("Document\","") try { $tb = $doc.GetSheetObject("Document\$tbId") if ($tb) { $tb.Close() | Out-Null; Write-Host " - removed $tbId" } } catch {} } } } } } # Create fresh tablebox $tb = $targetSheet.CreateTableBox() Start-Sleep -Milliseconds 400 # Populate via AddField (THIS is the working pattern) $added = 0; $failed = @() foreach ($f in $Fields) { try { $tb.AddField($f) | Out-Null $added++ } catch { $failed += $f } } Write-Host "populated $added/$($Fields.Count) fields" if ($failed.Count) { Write-Host "missed: $($failed -join ', ')" } $doc.Save() Start-Sleep -Milliseconds 500 $doc.CloseDoc() $qv.Quit() Write-Host "DONE"