Excel和Powershell:批量查找并replace公式中使用的URL

我正在创build一个脚本,我将提供将执行以下操作的SharePoint 2007文档库列表:

  1. 在Excel中,查找链接到其他工作簿+工作表(XLS / XLSX)的单元格内的公式
  2. 如果find,请使用http://servernew/sites/sitecollection/doclibreplace公式链接http://serverold/site/doclib/并保存
  3. 否则,请closures工作簿并转到下一个日志完整URL和任何更改的文件名

使用这个链接上的代码作为我的出发点,我不能得到以下工作:

  1. 正则expression式使脚本检测公式中的URL
  2. 修改脚本以在单元格内的公式中用新pathreplace旧path。
  3. 一个为每个分支处理,当发现匹配(保存和closures),当它没有find(只是closures)

我没有详细讨论我所做的所有研究(信息非常浅显),只是在另一个线程中提到可以在Excel中集中这些链接,但没有给出示例或链接,当我尝试枚举PowerShell中的链接集合 (安装了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() 

感谢任何能为您提供帮助的人。 最好的,灰

你会考虑简单地使用:

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

更新:我最初以为你正在使用正则expression式(只),但通过阅读脚本,我认为你需要更多的帮助。

让我来看看相关代码的一部分:

 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:\ temp \ a \中创build了一个简单的电子表格(a2.xls)

 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} 

这就是为什么你可能会更好:

  • 以string的forms读取单元格的内容,
  • 只replace服务器名称
  • 如果单元格没有你正在寻找的东西,将不会做任何事情和$改变= $公式
  • 如果没有,请回到新的公式。

当然,你不需要使用“replace”不是唯一的方法,但你得到的想法…

希望这可以帮助!