Excel& Powershell:Bulk查找并替换公式中使用的URL

时间:2013-08-30 16:21:32

标签: regex excel powershell

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

  1. 在Excel中,在单元格中查找链接到其他工作簿+工作表的公式(XLS / XLSX)
  2. 如果找到,请将公式链接http://serverold/site/doclib/替换为http://servernew/sites/sitecollection/doclib并保存
  3. 否则,请关闭工作簿并转到下一个Log full URL和任何更改的文件名
  4. 使用此link上的代码作为我的起点,我无法完成以下工作:

    1. 使脚本检测公式
    2. 中的URL的正则表达式
    3. 修改脚本,将旧路径替换为单元格内公式中的新路径。
    4. 每个分支的,以便在找到匹配项时保存(保存并关闭)以及何时找不到(只是关闭)
    5. 我没有详细介绍我所做的所有研究(信息在实地非常清晰),只是在另一个线程中提到你可以在Excel中集中枚举这些链接,但没有示例或链接当我尝试在PowerShell中枚举links collection(安装了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()
      

      感谢任何可以提供帮助和时间的人。 最好成绩, 灰

1 个答案:

答案 0 :(得分:3)

你会考虑简单地使用:

$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:\ temp \ a \

中创建了一个简单的电子表格(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 :

您没有看到我的来源,但让我告诉您:它正在从公式中提取网址。所以,如果我更改名称和地址......不幸的是,我不能。实际上,我可以将地址更改为指向新服务器,但其“name”属性是只读的(请参阅它没有设置):

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将不会做任何事情和$ changed = $式
  • 如果没有,请回到新公式。

当然,你不需要使用-replace不是唯一的方法,但你明白了......

希望这有帮助!