通过REST上传含ENUM的RDL至PowerBI时出现编译错误
解决PowerBI API上传含Enum自定义代码的Paginated报表报错问题
问题背景
需将数百个客户自定义SSRS报表迁移至指定PowerBI工作区的Paginated Reports,无SSRS服务器,RDL文件从私有数据库导出到本地。使用PowerShell脚本调用PowerBI API上传时,部分包含Enum自定义日期格式化代码的报表失败,报错核心为Statement cannot appear within an Enum body. End of Enum assumed,但手动上传这类报表可正常运行。
自定义代码示例
Enum DateTimePatterns ShortTimeFormat = 1 LongTimeFormat = 2 ShortDateFormat = 3 LongDateFormat = 4 ShortDateShortTimeFormat = 5 LongDateShortTimeFormat = 6 ShortDateLongTimeFormat = 7 LongDateLongTimeFormat = 8 End Enum Function FormatDate(ByVal dateToFormat As DateTime, Optional ByVal FormatOption As DateTimePatterns = DateTimePatterns.ShortDateShortTimeFormat) As String Dim FormattedDate As String FormattedDate = String.Empty If dateToFormat > DateTime.MinValue Then Select Case FormatOption Case DateTimePatterns.ShortTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.LongTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!LongTimeFormat.Value) Case DateTimePatterns.ShortDateFormat : FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value) Case DateTimePatterns.LongDateFormat : FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value) Case DateTimePatterns.ShortDateShortTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.LongDateShortTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.ShortDateLongTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) Case DateTimePatterns.LongDateLongTimeFormat : FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) End Select End If Return FormattedDate End Function
报表表达式示例
=Code.FormatDate(Globals!ExecutionTime, Code.DateTimePatterns.LongDateShortTimeFormat)
完整报错信息
Invoke-RestMethod : {"error":{"code":"PaginatedReportAuthoringError","pbi.error":{"code":"PaginatedReportAuthoringError","parameters":{},"details":[{"code":"RdlWorkloadErrorCode","detail":{"type":1,"value":"PaginatedReportAuthoringError"}},{"code":"RdlWorkloadErrorMessage","detail":{"type":1,"value":"Report is invalid. ErrorCode: rsUnexpectedCompilerError, Details: An unexpected error occurred while compiling expressions. Native compiler return value: \"[BC30619] Statement cannot appear within an Enum body. End of Enum assumed.\"."}},{"code":"RdlWorkloadErrorTitle","detail":{"type":1,"value":null}},{"code":"RdlWorkloadErrorContractName","detail":{"type":1,"value":"V1_MessageContainsPiiNonTranslated"}},{"code":"RdlWorkloadErrorInternalErrorMessage","detail":{"type":1,"value":null}},{"code":"RdlWorkloadErrorCulprit","detail":{"type":1,"value":"User"}},{"code":"PaginatedReportAuthoringError","detail":{"type":1,"value":"Report is invalid. ErrorCode: rsUnexpectedCompilerError, Details: An unexpected error occurred while compiling expressions. Native compiler return value: \"[BC30619] Statement cannot appear within an Enum body. End of Enum assumed.\"."}},{"code":"HostMode","detail":{"type":1,"value":"AutoPremium"}},{"code":"CapacityObjectId","detail":{"type":1,"value":"841ED558-4F06-4A6D-9E31-B9FB12FA96EE"}}],"exceptionCulprit":1}}} At C:\Users\me\Documents\Migrations\PublishRDLFilesToPowerBI_devto.ps1:36 char:15 + ... $report = Invoke-RestMethod -Uri $url -Method Post -Headers $header ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
解决方案
方案1:标准化VB代码格式(适配API解析逻辑)
API的RDL代码解析器对VB格式的敏感度高于手动上传流程,需调整代码格式:
- 移除
Case语句末尾多余的冒号 - 确保Enum定义的缩进、换行完全标准化
调整后的代码示例:
Enum DateTimePatterns ShortTimeFormat = 1 LongTimeFormat = 2 ShortDateFormat = 3 LongDateFormat = 4 ShortDateShortTimeFormat = 5 LongDateShortTimeFormat = 6 ShortDateLongTimeFormat = 7 LongDateLongTimeFormat = 8 End Enum Function FormatDate(ByVal dateToFormat As DateTime, Optional ByVal FormatOption As DateTimePatterns = DateTimePatterns.ShortDateShortTimeFormat) As String Dim FormattedDate As String FormattedDate = String.Empty If dateToFormat > DateTime.MinValue Then Select Case FormatOption Case DateTimePatterns.ShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.LongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongTimeFormat.Value) Case DateTimePatterns.ShortDateFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value) Case DateTimePatterns.LongDateFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value) Case DateTimePatterns.ShortDateShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.LongDateShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case DateTimePatterns.ShortDateLongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) Case DateTimePatterns.LongDateLongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) End Select End If Return FormattedDate End Function
方案2:替换Enum为常量定义(绕开Enum解析问题)
如果格式调整无效,可将Enum替换为全局常量,避免API解析Enum时出错:
Const ShortTimeFormat = 1 Const LongTimeFormat = 2 Const ShortDateFormat = 3 Const LongDateFormat = 4 Const ShortDateShortTimeFormat = 5 Const LongDateShortTimeFormat = 6 Const ShortDateLongTimeFormat = 7 Const LongDateLongTimeFormat = 8 Function FormatDate(ByVal dateToFormat As DateTime, Optional ByVal FormatOption As Integer = ShortDateShortTimeFormat) As String Dim FormattedDate As String FormattedDate = String.Empty If dateToFormat > DateTime.MinValue Then Select Case FormatOption Case ShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortTimeFormat.Value) Case LongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongTimeFormat.Value) Case ShortDateFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value) Case LongDateFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value) Case ShortDateShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case LongDateShortTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!ShortTimeFormat.Value) Case ShortDateLongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!ShortDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) Case LongDateLongTimeFormat FormattedDate = Format(dateToFormat, Report.Parameters!LongDateFormat.Value + " " + Report.Parameters!LongTimeFormat.Value) End Select End If Return FormattedDate End Function
同时报表中的表达式需修改为:
=Code.FormatDate(Globals!ExecutionTime, Code.LongDateShortTimeFormat)
方案3:采用二进制方式上传RDL文件(匹配手动上传逻辑)
检查PowerShell脚本的上传方式,若使用文本方式提交RDL内容,改为二进制流上传,避免API对文本内容的额外解析:
$accessToken = "你的PowerBI访问令牌" $groupId = "目标工作区ID" $rdlPath = "C:\path\to\your\report.rdl" $rdlContent = [System.IO.File]::ReadAllBytes($rdlPath) $headers = @{ "Authorization" = "Bearer $accessToken" "Content-Type" = "application/octet-stream" } $url = "https://api.powerbi.com/v1.0/myorg/groups/$groupId/reports/Import" Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $rdlContent
内容的提问来源于stack exchange,提问作者svenGUTT
相关产品推荐
相关产品推荐

