2013-08-30 50 views
1

我正在創建一個腳本,我將提供SharePoint 2007中的文檔庫列表中使用的URL來將做到以下幾點:的Excel和PowerShell的:批量查找和替換公式

  1. 在Excel中,查找鏈接到其他工作簿+表(XLS/XLSX)
  2. 如果發現的細胞內結構式中,與http://servernew/sites/sitecollection/doclib更換式鏈路http://serverold/site/doclib/和保存
  3. 否則,關閉工作簿並移動到下一個登錄完整的URL和文件名任何變化

使用這個link的代碼作爲我的出發點,我不能讓下面的工作:

  1. 正則表達式表達使腳本檢測在公式中的URL
  2. 修改腳本,以取代舊單元格內公式中的新路徑。
  3. 一個每個分支處理比賽時被發現(保存並關閉),當它沒有找到(只是接近)

我不會詳細討論所有的研究我已經完成(信息非常清晰),只是在另一個線程中提到您可以在Excel中集中枚舉這些鏈接,但沒有給出任何示例或鏈接,並且我試圖枚舉links collection PowerShell(with Excel 2010安裝)它是空的與我使用的示例工作簿,我知道這個意義上的「鏈接」。

實例列舉鏈接彙總:

$File = "C:\temp\example.xls" 
$Excel = New-Object -ComObject Excel.Application 
$Excel.visible = $true 
$Workbook = $Excel.workbooks.open($file) 
$Workbook.LinkSources 

所以這引出了一個問題,該方法是正確的?

例Excel公式

=+'http://server.old/site/site/Work in Progress `enter code here`Documents/Statements/[Hierarchy2011.xls]Reports'!$AD$37+'http://server.old/site/site/Work in Progress Documents/ 

腳本枚舉鏈接(從我爲我的出發點中提到的鏈接) -

$path = "C:\temp" 
$excelSheets = Get-Childitem -Path $path -Include *.xls,*.xlsx -Recurse 
$excel = New-Object -comobject Excel.Application 
$excel.visible = $false 

foreach($excelSheet in $excelSheets) 
{ 
$workbook = $excel.Workbooks.Open($excelSheet) 
"There are $($workbook.Sheets.count) sheets in $excelSheet" 

For($i = 1 ; $i -le $workbook.Sheets.count ; $i++) 
{ 
    $worksheet = $workbook.sheets.item($i) 
    "`tLooking for links on $($worksheet.name) worksheet" 
    $rowMax = ($worksheet.usedRange.rows).count 
    $columnMax = ($worksheet.usedRange.columns).count 
    For($row = 1 ; $row -le $rowMax ; $row ++) 
    { 
    For($column = 1 ; $column -le $columnMax ; $column ++) 
    { 
    [string]$formula = $workSheet.cells.item($row,$column).formula 
    if($formula -match "\w?:\\\w*\\\[\w*\.xls\w?\]") {"`t`t$($formula)"} 
    } #end for $column 
    } #end for $row 
    $worksheet = $rowmax = $columnMax = $row = $column = $formula = $null 
} #end for 
$workbook.saved = $true 
$workbook.close() 
} #end foreach 

$excel.quit() 
$excel = $null 
[gc]::collect() 
[gc]::WaitForPendingFinalizers() 

由於任何人誰可以幫助和您的時間。 最好成績, 灰

+0

+1很好的問題。 – brettdj

回答

2

您會考慮使用簡單:

$formula -replace 'http://server.old/','http://server.new/' 

更新:我最初以爲您在使用正則表達式(只)有問題,但通過該腳本讀書,我想你需要比這更有幫助。

讓我把與自己相關的代碼部分:

For($i = 1 ; $i -le $workbook.Sheets.count ; $i++) 
{ 
    $worksheet = $workbook.sheets.item($i) 
    "`tLooking for links on $($worksheet.name) worksheet" 
    $rowMax = ($worksheet.usedRange.rows).count 
    $columnMax = ($worksheet.usedRange.columns).count 
    For($row = 1 ; $row -le $rowMax ; $row ++) 
    { 
    For($column = 1 ; $column -le $columnMax ; $column ++) 
    { 
    [string]$formula = $workSheet.cells.item($row,$column).formula 
    ## This is irrelavant, it's trying to match a file... 
    ##  if($formula -match "\w?:\\\w*\\\[\w*\.xls\w?\]") {"`t`t$($formula)"} 

    $changed = $formula -replace 'http://server.old/','http://server.new/' 
    if ($formula -ne $changed) { 
     $workSheet.cells.item($row,$column).formula = $changed 
    } 


    } #end for $column 
    } #end for $row 
    $worksheet = $rowmax = $columnMax = $row = $column = $formula = $null 
} #end for 

## The line below is actually cause file to be not saved when closing it as you are telling excel, hey you are saved. 
## $workbook.saved = $true 
## I would use this: 
if (!$Workbook.saved) { $workbook.save() } 
$workbook.close() 
} #end foreach 

現在,雖然我對這個,讓我告訴你,我怎麼會去試圖修改別人的劇本之前,調查這個業務:在控制檯調查對象!

對於這個例子,我在C創建了一個簡單的電子表格(a2.xls):\ TEMP \一個\

PS H:\> $excel = New-Object -com Excel.Application 
PS H:\> $workbook = $excel.Workbooks.Open("C:\temp\a\a2.xls") 
PS H:\> $worksheet=$workbook.Sheets.item(1) 

樂趣的開始:

PS H:\> $worksheet |get-member -Type Properties 


    TypeName: System.__ComObject#{000208d8-0000-0000-c000-000000000046} 

Name        MemberType Definition 
----        ---------- ---------- 
Application      Property Application Application() {get} 
AutoFilter      Property AutoFilter AutoFilter() {get} 
AutoFilterMode     Property bool AutoFilterMode() {get} {set} 
Cells        Property Range Cells() {get} 
CircularReference     Property Range CircularReference() {get} 
CodeName       Property string CodeName() {get} 
Columns       Property Range Columns() {get} 
Comments       Property Comments Comments() {get} 
ConsolidationFunction    Property XlConsolidationFunction ConsolidationFunction() {get} 
ConsolidationOptions    Property Variant ConsolidationOptions() {get} 
ConsolidationSources    Property Variant ConsolidationSources() {get} 
Creator       Property XlCreator Creator() {get} 
CustomProperties     Property CustomProperties CustomProperties() {get} 
DisplayAutomaticPageBreaks  Property bool DisplayAutomaticPageBreaks() {get} {set} 
DisplayPageBreaks     Property bool DisplayPageBreaks() {get} {set} 
DisplayRightToLeft    Property bool DisplayRightToLeft() {get} {set} 
EnableAutoFilter     Property bool EnableAutoFilter() {get} {set} 
EnableCalculation     Property bool EnableCalculation() {get} {set} 
EnableFormatConditionsCalculation Property bool EnableFormatConditionsCalculation() {get} {set} 
EnableOutlining     Property bool EnableOutlining() {get} {set} 
EnablePivotTable     Property bool EnablePivotTable() {get} {set} 
EnableSelection     Property XlEnableSelection EnableSelection() {get} {set} 
FilterMode      Property bool FilterMode() {get} 
HPageBreaks      Property HPageBreaks HPageBreaks() {get} 
Hyperlinks      Property Hyperlinks Hyperlinks() {get} 
Index        Property int Index() {get} 

(縮短的輸出)。看到那裏的超鏈接屬性?那是你所指的嗎? 請看:

PS H:\> $worksheet.hyperlinks 


Application : Microsoft.Office.Interop.Excel.ApplicationClass 
Creator  : 1480803660 
Parent  : System.__ComObject 
Name   : http://old.server/adil1/hellow 
Range   : System.__ComObject 
Shape   : 
SubAddress : 
Address  : http://old.server/adil1/hellow 
Type   : 0 
EmailSubject : 
ScreenTip  : 
TextToDisplay : 

你看不到我的消息來源,但讓我告訴你:這是一個從公式中提取的URL。所以,如果我更改名稱和地址......很遺憾,我不能。我其實是可以改變地址指向新的服務器,但它的「名字」屬性爲只讀(見它沒有固定的):

PS H:\> $worksheet.hyperlinks |gm 


    TypeName: System.__ComObject#{00024431-0000-0000-c000-000000000046} 

Name    MemberType Definition 
----    ---------- ---------- 
Address   Property string Address() {get} {set} 
Name    Property string Name() {get} 

這就是爲什麼你可能會更好過:

  • 讀取小區作爲字符串的內容,
  • 只更換服務器名稱
  • 如果電池沒有你在找什麼-replace不會做任何事情,$改變= $公式
  • 如果不是,則返回新的公式。

當然,你並不需要使用-replace是不是唯一的方式,但你的想法...

希望這有助於!

+0

嗨Adil,謝謝。這已經解決了這個問題。你是個明星。 – AshFlaw

+0

你如何寫地址?我正在嘗試$ _Address = $ _。Address.Replace(「http:// old」,「http:// new」),並且不需要。 –

+0

@MatthewMcDermott這個已經在2年前回答和結束了。問作爲一個新問題併發布您的代碼+問題。 –