教程:为 SharePoint 网站生成和分析版本使用情况报告

通过了解站点上的版本存储,可以更好地优化版本历史记录设置,以满足组织的恢复目标并管理存储成本。

本教程介绍如何生成版本存储使用情况报告并对其进行分析,以便更好地了解站点的版本存储占用量。 报表还可用于运行应用不同版本限制或剪裁现有版本的 “假设”分析

本教程介绍如何:

  • 为网站或库生成版本存储使用情况报告文件。
  • 检查报表生成进度。
  • 了解报表文件。
  • 使用 Excel 或 PowerShell 分析版本存储使用情况。

在后面的教程中,请查看如何对生成的 CSV 报表运行影响分析。

开始之前

  1. 确定要了解其版本存储使用情况的 SharePoint 网站、OneDrive 帐户或文档库。
  2. 在 SharePoint 文档库中选择要将报表保存到的位置。
  3. 下载最新的SharePoint在线管理壳

注意

  1. 报表文件在指定的报表位置内生成。
  2. 报表位置必须位于 SharePoint 文档库本身内。
  3. 文档库中不能有与报表同名的文件。

为网站或库生成版本使用情况报告

可以通过运行 命令生成有关站点上当前版本存储使用情况的报告, New-SPOSiteFileVersionExpirationReportJob 也可以通过运行 New-SPOListFileVersionBatchDeleteJob 命令在库上生成报告。

在以下示例中,作业排队以在报表位置 https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv生成站点范围的报表。

New-SPOSiteFileVersionExpirationReportJob -Identity https://contoso.sharepoint.com/sites/site1 -ReportUrl "https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv"  

在以下示例中,作业将排队,以在报表位置 https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv生成库范围的报表。

New-SPOListFileVersionExpirationReportJob -Site https://contoso.sharepoint.com/sites/site1 -List "Documents" -ReportUrl "https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv"

检查报表生成进度

Get-SPOListFileVersionExpirationReportJobProgress使用 命令跟踪报表生成请求的进度。

下面的示例演示了如何检查网站范围的报表是否已完全填充并准备好进行分析。 

Get-SPOSiteFileVersionExpirationReportJobProgress -Identity https://contoso.sharepoint.com/sites/site1 -ReportUrl "https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv"

下面的示例演示了如何检查,如果库范围的报表已完全填充并准备好进行分析。  

Get-SPOListFileVersionExpirationReportJobProgress -Site https://contoso.sharepoint.com/sites/site1 -List "Documents" -ReportUrl "https://contoso.sharepoint.com/sites/sites1/reports/MyReports/VersionReport.csv"    

cmdlet 将返回 JSON 格式的响应。 返回的 json 响应具有名为 status 的键。 有关以下预期值之一,请参阅下表:

JSON 状态响应 解释
“completed” 作业已成功完成,报表已完全填充。
“in_progress” 有一个活动作业。 报表已部分填充。
“no_report_found” 没有填充指定文件的活动作业。
“failed” 由于错误消息,用于生成报表的作业失败。 检查“error_message”以获取失败的错误消息。

了解版本报告文件

生成的报表采用 CSV 格式,每行对应于文件版本。 下面是文件版本过期报告及其列细目的示例。

过期报告的屏幕截图。

第一行是包含文件版本标识符、版本元数据信息和过期时间戳的列标识符的标题。 压缩列用修复后表示 .Compact ,如果两个连续行具有相同的值,则不会重复值。 其他行表示文件版本,其中每行表示单个版本。
我们来了解此报表中显示的第一个文件版本。

  • 文件版本标识符: WebIdDocIdMajorVersionMinorVersion 唯一标识 SharePoint 网站中的每个版本。

  • 版本元数据标识符:WebUrl 指示 中的 https://contoso.sharepoint.com版本,并 FileUrl 指示此版本的文件位于 DocLib/MyDocument.docx。 换句话说,它位于名为 DocLib的文档库中,而该文件位于 的 DocLib 根文件夹中,名为 MyDocument.docx。

  • Size 指示版本需要 92,246 字节的存储。

  • 接下来的两列和 ModifiedBy_UserIdModifiedBy_DisplayName 指示用户 ID 为 6) 的用户 Michelle Harris (已创建此版本。

  • LastModifiedDate 指示版本内容的上次修改时间是 2023 年 3 月 13 日 22:36:09 UTC。 SnapshotDate 显示该版本在 2023 年 3 月 20 日 UTC 时间 16:56:51 成为历史版本。 IsSnapshotDateEstimated SnapshotDate显示实际快照日期。

  • 过期计划标识符:CurrentExpirationDate 指示此版本当前设置为永不过期。 AutomaticPolicyExpirationDate 显示,在自动过期策略下,此版本也设置为永不过期。 TargetExpirationDate 指示如果我们按照此计划进行剪裁,则会将此版本设置为永不过期。

注意

此报表中也包括存储在保留库中的文件版本。

让我们看一下第三个版本。

WebIdDocId 值为空,因为这些列是压缩列,由 表示。压缩修复后,这意味着它们应具有值。 如果查找该行上方的最后一个非空,则会找到 WebId4c7a58c1-01f2-4fa3-a730-44081a44f689、 和 DocId18c3e09c-b5be-48e7-a754-7a2ce53e0999

我们还可以看到, TargetExpirationDate 设置为 2023 年 4 月 19 日 UTC 18:08:53。 这意味着,如果我们根据此计划进行剪裁,则将此版本的到期日期设置为该时间。

注意

所有日期时间都以往返格式表示。 有关详细信息,请参阅Standard日期和时间格式字符串 - .NET |Microsoft Learn

分析站点的版本存储

在开始分析之前,应将报表文件中的 TargetExpirationDate 列更新为所需的日期,例如要过期的版本。 同样,如果为某个版本选择过去日期,则该版本将被视为“已过期的版本”,并在开始剪裁后立即删除。

可以通过编辑 csv 文件手动更新 中的 TargetExpirationDate 日期。 但是,可能需要手动更新的行太多。 若要批量更新列,可以使用 Excel 公式,也可以使用我们在 教程:运行“What-If”分析中提供的 PowerShell 脚本之一。 具体来说,可以选择剪裁模式,运行相应的脚本以获取基于该剪裁模式填写的更新 csv 文件 TargetExpirationDate ,然后从那里继续。

选项 1:使用 Excel 分析报表

AnalyzeReportFile_Template.xlsx打开共享的 Excel 工作簿。 可以在其中找到以下工作表。

  • 配置:使用此工作表可设置用于生成不同报表视图的日期范围。
  • 数据集:此工作表是从报表文件导入的原始数据集。 从此数据集构造各种报告摘要视图。
  • 预设报告:下面是预设视图列表,可用于了解对网站中存储的版本应用所选设置的影响:
    • 摘要:分析新设置下此站点的版本存储的当前状态和已删除的版本分发。
    • 受影响的用户:查看在新设置下其版本将受到影响的用户。
    • 版本计数:一个表和图,显示当前计划下一段时间内可用的版本数以及新计划下可用的版本数。
    • 版本大小分析:比较在当前计划下随时间推移删除的版本的大小,以及新计划下可用的版本数。
    • 文件级别分析:查看新设置下的文件级别版本删除。

按照以下步骤填充工作簿:

  1. “配置” 工作表中,输入 单元格 B3 中 What-If 报表文件的完整路径。

    配置工作表的屏幕截图。

  2. 如果要更改 “可用版本数 ”工作表或“ 已过期版本” 工作表中的图形日期范围,请更改单元格 B6、B7、B10 和/或 B11 中的相应值。 这是可选的。

    分析版本配置的屏幕截图。

  3. 在 Excel 顶部,选择“ 数据 ”选项卡,然后在功能区中选择“ 全部刷新 ”按钮。

    “分析版本数据”选项卡的屏幕截图。

  4. “文件级别分析”工作表上,自动填充“版本数”和“删除后剩余版本数”列。

    计算工作表 1 的屏幕截图。

    计算工作表 2 的屏幕截图。

    提示

    可以选择包含数据的单元格,然后双击填充手柄以完成自动填充。 Excel 填充手柄的图标。

  5. “受影响的用户” 工作表上,自动填充 “将删除的版本数” 列。

    受影响的用户工作表的屏幕截图。

现在,所有工作表都应是最新的。 可以检查感兴趣的信息。

选项 2:使用 PowerShell 分析报表

  1. 将脚本另存为名为 AnalyzeReportFile.ps1 的文件。
# save this file as AnalyzeReportFile.ps1

Param(
  [Parameter(Mandatory=$true)][string] $ReportLocalFilePath,
  [Parameter(Mandatory=$false)][int]$ShowFilesWithFewerThanNVersions=10,
  [Parameter(Mandatory=$false)][DateTime]$TimelineStartDate=[DateTime]::Now,
  [Parameter(Mandatory=$false)][int]$TimelineStepDays=10,
  [Parameter(Mandatory=$false)][int]$TimelineNumSteps=10
)
function Import-Dataset($DatasetFilePath)
{
  $Dataset = Import-CSV $DatasetFilePath
  $Columns = $Dataset `
    | Get-Member -MemberType 'NoteProperty' `
    | Select-Object -ExpandProperty Name
  $CompactColumns = $Columns | Where-Object { $_ -Match ".Compact" }
   
  $Timer = [Diagnostics.Stopwatch]::StartNew()
  for ($RowIndex = 0; $RowIndex -lt $Dataset.Count; $RowIndex++)
  {
    if ($RowIndex -gt 0)
    {
      $PrevRow = $Dataset[$RowIndex-1]
    }
    $Row = $Dataset[$RowIndex]
   
    foreach ($ColName in $Columns)
    {
      if ([string]::IsNullOrEmpty($Row.$ColName))
      {
        if (($ColName -in $CompactColumns) -and ($RowIndex -gt 0))
        {
          $Row.$ColName = $PrevRow.$ColName
        }
        else
        {
          $Row.$ColName = $null
        }
      }
    }
   
    $Row."WebId.Compact" = [Guid]$Row."WebId.Compact"
    $Row."DocId.Compact" = [Guid]$Row."DocId.Compact"
    $Row."MajorVersion" = [Int32]$Row."MajorVersion"
    $Row."MinorVersion" = [Int32]$Row."MinorVersion"
    $Row."WebUrl.Compact" = [String]$Row."WebUrl.Compact"
    $Row."FileUrl.Compact" = [String]$Row."FileUrl.Compact"
    $Row."Size" = [Int64]$Row."Size"
    $Row."ModifiedBy_UserId.Compact" = [String]$Row."ModifiedBy_UserId.Compact"
    $Row."ModifiedBy_DisplayName.Compact" = [String]$Row."ModifiedBy_DisplayName.Compact"
    $Row."LastModifiedDate" = [DateTime]$Row."LastModifiedDate"
    $Row."SnapshotDate" = [DateTime]$Row."SnapshotDate"
    $Row."IsSnapshotDateEstimated" = [bool]$Row."IsSnapshotDateEstimated"
    $Row."CurrentExpirationDate" = [System.Nullable[DateTime]]$Row."CurrentExpirationDate"
    $Row."AutomaticPolicyExpirationDate" = [System.Nullable[DateTime]]$Row."AutomaticPolicyExpirationDate"
    $Row."TargetExpirationDate" = [System.Nullable[DateTime]]$Row."TargetExpirationDate"
    $Percent = [Math]::Ceiling(100 * $RowIndex / $Dataset.Count)
    Write-Progress `
      -Activity "Reading dataset" `
      -Status "$Percent% Complete ($($RowIndex + 1) / $($Dataset.Count) rows):" `
      -PercentComplete $Percent `
      -SecondsRemaining $(($Dataset.Count - ($RowIndex + 1)) / (($RowIndex + 1) / $Timer.Elapsed.Totalseconds))
  }
  $Timer.Stop()
  return $Dataset
}
function Get-NumVersionExpiresByDate($Dataset, $ColName, $DateCutoff)
{
  $VersionsExpired = $Dataset | Where-Object { ($null -ne $_.$ColName) -and ($_.$ColName -le $DateCutoff) }
  $IsTodayStr = ""
  If ((Get-Date).Date -eq ($DateCutoff).Date) 
  {
    $IsTodayStr = "*"
  }
  return [PSCustomObject]@{
    Today              = $IsTodayStr
    Date              = $DateCutoff
    NumberOfVersionsAvailable    = $Dataset.Count - $VersionsExpired.Count
    NumberOfVersionsExpired     = $VersionsExpired.Count
    SizeOfVersionsExpiredInBytes  = ($VersionsExpired | Measure-Object Size -Sum).Sum
  }
}
function Get-FilesWithFewerThanNVersions($Dataset, $NumVersions)
{
  $AvailableVersionsByFile = $Dataset `
    | Where-Object { ($null -eq $_.TargetExpirationDate) -or ($_.TargetExpirationDate -gt [DateTime]::Now) } `
    | Group-Object -Property WebId.Compact, DocId.Compact
  $AvailableFilesWithNotEnoughVersions = @{}
  # Files with some versions left but not enough
  $AvailableVersionsByFile `
    | Where-Object Count -lt $NumVersions `
    | ForEach-Object { $AvailableFilesWithNotEnoughVersions[$_.Name] = $_.Count }
  # Files with 0 versions left
  $Dataset `
    | Group-Object -Property WebId.Compact, DocId.Compact `
    | Where-Object { $AvailableVersionsByFile.Name -notcontains $_.Name } `
    | ForEach-Object { $AvailableFilesWithNotEnoughVersions[$_.Name] = 0 }
  # Stitch all of the data together
  return $Dataset `
    | Group-Object -Property WebId.Compact, DocId.Compact `
    | Where-Object Count -ge $NumVersions `
    | Where-Object { $AvailableFilesWithNotEnoughVersions.Contains($_.Name) } `
    | ForEach-Object `
      {
        $fileUrl = $_.Group[0]."WebUrl.Compact" + "/" + $_.Group[0]."FileUrl.Compact"
        $numberOfVersionsAvailableBeforeTrim = $_.Count
        $numberOfVersionsAvailableAfterTrim = $AvailableFilesWithNotEnoughVersions[$_.Name]
        $numberOfVersionsTrimmed = $numberOfVersionsAvailableBeforeTrim - $numberOfVersionsAvailableAfterTrim
        [PSObject]::new() | 
          Add-Member -PassThru -NotePropertyMembers ([Ordered]@{
            FileUrl = $fileUrl
            NumberOfVersionsAvailableBeforeTrim = $numberOfVersionsAvailableBeforeTrim
            NumberOfVersionsAvailableAfterTrim = $numberOfVersionsAvailableAfterTrim
            NumberOfVersionsTrimmed = $numberOfVersionsTrimmed
          })
      } `
    | Sort-Object -Property NumberOfVersionsAvailableAfterTrim
}
function Get-MostImpactedUsers($Dataset)
{
  $VersionsExpired = $Dataset | Where-Object { ($null -ne $_.TargetExpirationDate) -and ($_.TargetExpirationDate -le [DateTime]::Now) }
  return $VersionsExpired `
    | Group-Object -Property ModifiedBy_UserId.Compact `
    | Select-Object `
      @{ L = "UserId"; E = { $_.Group[0]."ModifiedBy_UserId.Compact" } }, `
      @{ L = "UserDisplayName"; E = { $_.Group[0]."ModifiedBy_DisplayName.Compact" } },
      @{ L = "NumberOfVersionsTrimmed"; E = { $_.Count } } `
    | Sort-Object -Property NumberOfVersionsTrimmed -Descending
}
$Dataset = Import-Dataset -DatasetFilePath $ReportLocalFilePath
$CurrentExpirationSummaryTable = @()
$TargetExpirationSummaryTable = @()
$Timer = [Diagnostics.Stopwatch]::StartNew()
for ($Step = 0; $Step -lt $TimelineNumSteps; $Step++)
{
  $DateCutOff = $TimelineStartDate.AddDays($TimelineStepDays * $Step)
  $CurrentExpirationSummaryTable += `
    Get-NumVersionExpiresByDate -Dataset $Dataset -ColName CurrentExpirationDate -DateCutoff $DateCutOff
  $TargetExpirationSummaryTable += `
    Get-NumVersionExpiresByDate -Dataset $Dataset -ColName TargetExpirationDate -DateCutoff $DateCutOff
}
$Timer.Stop()
Write-Host "===========================" -ForegroundColor Yellow
Write-Host "Current Expiration Schedule" -ForegroundColor Yellow
Write-Host "===========================" -ForegroundColor Yellow
$CurrentExpirationSummaryTable | Format-Table -Autosize | Out-String | Write-Host
Write-Host "Total elapsed seconds: $($Timer.Elapsed.TotalSeconds / 2)" -ForegroundColor Green
Write-Host
Write-Host "==========================" -ForegroundColor Yellow
Write-Host "Target Expiration Schedule" -ForegroundColor Yellow
Write-Host "==========================" -ForegroundColor Yellow
$TargetExpirationSummaryTable | Format-Table -Autosize | Out-String | Write-Host
Write-Host "Total elapsed seconds: $($Timer.Elapsed.TotalSeconds / 2)" -ForegroundColor Green
Write-Host
Write-Host "================================" -ForegroundColor Yellow
Write-Host "Files with Fewer Than $ShowFilesWithFewerThanNVersions Versions" -ForegroundColor Yellow
Write-Host "================================" -ForegroundColor Yellow
$Timer = [Diagnostics.Stopwatch]::StartNew()
Get-FilesWithFewerThanNVersions -Dataset $Dataset -NumVersions $ShowFilesWithFewerThanNVersions | Format-Table -Autosize | Out-String | Write-Host
$Timer.Stop()
Write-Host "Total elapsed seconds: $($Timer.Elapsed.TotalSeconds)" -ForegroundColor Green
Write-Host
Write-Host "==============" -ForegroundColor Yellow
Write-Host "Users Impacted" -ForegroundColor Yellow
Write-Host "==============" -ForegroundColor Yellow
$Timer = [Diagnostics.Stopwatch]::StartNew()
Get-MostImpactedUsers -Dataset $Dataset | Format-Table -Autosize | Out-String | Write-Host
$Timer.Stop()
Write-Host "Total elapsed seconds: $($Timer.Elapsed.TotalSeconds)" -ForegroundColor Green
Write-Host
  1. 打开 PowerShell 并运行以下命令,将占位符值替换为相应的值。

注意

使用 PowerShell 7 运行命令。 可以按照以下说明安装 PowerShell 7: 在 Windows 上安装 PowerShell - PowerShell |Microsoft Learn

. “<path to AnalyzeReportFile.ps1>” –ReportLocalFilePath “<path to the file version expiration What-If report .csv file>”

分析报表 powershell 命令的屏幕截图。

  1. 输出显示四个表:
  • 当前过期计划: 此表包含版本(按原样)的时序摘要。 它具有以下列:

    1. 日期:第一列表示日期。
    2. NumberOfVersionsAvailable:当前计划下该日期可用的版本数。
    3. NumberOfVersionsExpired:当前计划下该日期过期的版本数。
    4. SizeOfVersionsExpiredMB:当前计划下该日期过期的版本的大小。

    当前过期计划的屏幕截图。

  • 目标过期计划: 此表与当前过期计划相同,但反映的是更新的计划。 仅当你想要通过更改文件版本过期报告中 的 TargetExpirationDate 列来测试不同的过期方案时,此表才有用。

    目标过期计划的屏幕截图。

  • 版本少于 10 个的文件: URL 列表,以及删除前后版本数小于 10 的文件,这些文件在立即删除后的版本数小于 10 (但在立即删除) 之前超过 10 个。

    版本少于 10 个的文件的屏幕截图。

  • 受影响的用户: 将立即删除其版本的用户。

    受影响的用户的屏幕截图。

(可选)可以调整参数:

  • TimelineStartDate:上述表 1 和表 2 的开始日期。
  • TimelineStepDays:上面表 1 和表 2 的行之间的天数。
  • TimelineNumSteps:要为上述表 1 和表 2 计算的行数。
  • ShowFilesWithFewerThanNVersions:上述表 3 中版本数的阈值。