Mit diesem Skript ist das machbar (zumindest fĂĽr die AL-Dateien aus unserem Add-on, die alle noch eine Objekt-ID enthalten, funktioniert es einwandfrei , falls mit anderen Dateien Fehler auftauchen, bitte Beispiele reinstellen).
Die Dateien werden ausgehehend von dem Ordner, wo das Objektpaket liegt (das kann über ein Fenster ausgewählt werden)…
…in einem Unterordner SPLITBCOBJ erzeugt.
Bei der Dateinamenstruktur fĂĽr AL-Dateien kursieren ja mittlerweile verschiedene Varianten.
Im Skript werden weitgehend die Namensformatierungen des Txt2Al-Tools verwendet (nicht, weil ich die schön finde, sondern weil sie eben so sind, wie sie sind ), nur bei Extensions (für Tables und Pages) fehlt die Nummer des Objekts, auf das die Extension angewandt wird, weil sich dieses aus dem Dateiinhalt nicht entnehmen lässt. Ansonsten sind andere Namensstrukturen natürlich im Skript nach Bedarf anpassbar.
- Code: Alles auswählen
function Split-ALObjectFile
{
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "AL Object Files (*.al)|*.al"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
$inputfile = Get-FileName "C:\temp" # This is the default path in OpenFile window.
if ($inputfile -eq "") {throw 'Please select a file'}
[decimal]$filesize = ((Get-Item $inputfile).length/1MB)
$filesize =[math]::round($filesize,2)
$inputfile = resolve-path $inputfile
$WorkingFolder = Split-Path -Parent $inputfile
if (Test-path "$WorkingFolder\SPLITBCOBJ\")
{Remove-Item -path "$WorkingFolder\SPLITBCOBJ\" -Recurse -Force}
Write-Host "Splitting BC/NAV objects from $inputfile (Size: $filesize MB) to $WorkingFolder\SPLITBCOBJ\, this may take a while..." -ForegroundColor Yellow
$starttime = date
$Sr = new-object System.IO.StreamReader($inputfile,[system.text.encoding]::GetEncoding(65001))
[int]$ObjCnt = 0
[int]$TabCnt = 0
[int]$PagCnt = 0
[int]$RepCnt = 0
[int]$CodCnt = 0
[int]$XmlCnt = 0
[int]$QueCnt = 0
[int]$TabExtCnt = 0
[int]$PagExtCnt = 0
[int]$EnumCnt = 0
[int]$EnumExtCnt = 0
[int]$CtrlAddInCnt = 0
[int]$PagCstmCnt = 0
[int]$KeysCnt = 0
[int]$DotNetCnt = 0
[int]$ProfileCnt = 0
while (-not $Sr.EndOfStream)
{
$Currline = $sr.ReadLine()
if ($Currline.StartsWith('table ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('tableextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('page ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('pageextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('pagecustomization ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('report ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('query ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('codeunit ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('enum ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('enumextension ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('keys ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('profile ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('xmlport ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('dotnet ')) {$NewObject = $True}
Elseif ($Currline.StartsWith('controladdin ')) {$NewObject = $True}
else {$NewObject = $false}
if ($NewObject)
{
$IsExtension = $false
$dblquotes = [char]34
[String]$ObjectChars = $Currline.Substring(0,5)
[String]$ObjectChar = $Currline.Substring(6,1)
write-host $currline
$IsExtension = ($Currline.indexof(' extends ') -gt 0)
if ($IsExtension)
{
$PosExtends = $Currline.indexof(' extends ')
if ($PosExtends -gt 0)
{
$ObjectExtendedName = $Currline.Substring($PosExtends+9)
$CleanObjectExtendedName = $ObjectExtendedName.TrimStart('"')
$CleanObjectExtendedName = $CleanObjectExtendedName.TrimEnd(' ')
$CleanObjectExtendedName = $CleanObjectExtendedName.TrimEnd('"')
$CleanObjectExtendedName = $CleanObjectExtendedName.Trim('/')
}
else
{$CleanObjectExtendedName = ''}
}
else
{$CleanObjectExtendedName = ''}
#write-host $ObjectChars
#write-host $ObjectChar
$PosFirstBlank = $Currline.indexof(' ')
$Currline2 = $Currline.Substring($PosFirstBlank+1)
$PosSecondBlank = $Currline2.indexof(' ')
if ($PosSecondBlank -ne 0)
{$ObjectName = $Currline2.Substring($PosSecondBlank+1)}
else
{$ObjectName = ''}
if ($ObjectName.Startswith('"'))
{
$CleanObjectName = $ObjectName.TrimStart('"')
$CleanObjectName = $CleanObjectName.TrimEnd(' ')
$CleanObjectName = $CleanObjectName.TrimEnd('"')
$CleanObjectName = $CleanObjectName.Trim('/')
}
else
{$CleanObjectName = $ObjectName.Trim('/')}
write-host $currline2
$ObjectLine = $currline.Split(' ')
$ObjCnt++
Switch ($ObjectChars)
{
'table' {
if (!$IsExtension)
{
$TabCnt++;$ObjectType = 'Table'
}
else
{
$TabExtCnt++;$ObjectType = 'TableExt'
}
}
'page ' {
$PagCnt++;$ObjectType = 'Page'}
'pagee' {$PagExtCnt++; $ObjectType = 'PageExt'}
'pagec' {$PagCstmCnt++;$ObjectType = 'PageCstm'}
'repor' {$RepCnt++;$ObjectType = 'Report'}
'codeu'{$CodCnt++;$ObjectType = 'Codeunit'}
'xmlpo' {$XmlCnt++;$ObjectType = 'XMLport'}
'enum ' {$enumCnt++;$ObjectType = 'Enum'}
'enume' {$enumExtCnt++;$ObjectType = 'EnumExt'}
'keys ' {$KeysCnt++;$ObjectType = 'Keys'}
'profi' {$ProfileCnt++;$ObjectType = 'Profile'}
'query ' {$QueCnt++;$ObjectType = 'Query'}
'dotnet ' {$DotNetCnt++;$ObjectType = 'DotNet'}
'controladdin ' {$CtrlAddinCnt++;$ObjectType = 'ControlAddin'}
}
if (!$IsExtension)
{
If (($ObjectLine[2] -eq '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + '.al'}
elseif (($ObjectLine[1] -ne '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + $ObjectLine[1] + '.al'}
elseif (($ObjectLine[1] -ne '') -and ($CleanObjectName -eq ''))
{$ObjectFileName = $ObjectType + $ObjectLine[1] + $CleanObjectName + '.al'}
else
{$ObjectFileName = $ObjectType + ' ' + $ObjectLine[1] + ' - ' + $CleanObjectName + '.al'}
}
else
{
$ObjectFileName = 'Modification - ' + $CleanObjectExtendedName + '(' + $ObjectType + ')' + '.al'
}
#write-host "Object Type: $Objecttype"
#write-host "Object Name: $CleanObjectName"
#write-host 'Object ID: ' $ObjectLine[1]
#write-host "Object Extended Name: $CleanObjectExtendedName"
$ObjectFileName = $ObjectFileName.replace('/','')
write-host "File Name: $ObjectFileName"
$Objectfile = New-Item -path "$WorkingFolder\SPLITBCOBJ\$ObjectFileName" -type file -force
$sw = new-object System.IO.Streamwriter($Objectfile,$false,[system.text.encoding]::GetEncoding(65001))
#IF (Test-Path $ObjectFile) {Remove-Item $ObjectFile}
}
if (-not $Currline.StartsWith('}'))
{$sw.writeline($Currline)}
else
{
$sw.writeline($Currline)
$sw.writeline()
$sw.Flush()
}
}
$endtime = date
$time = $endtime - $starttime
Write-Host "$ObjCnt BC/NAV objects splitted to $WorkingFolder\SPLITBCOBJ\ in $($time.Minutes)m:$($time.Seconds)s:$($time.Milliseconds)ms" -ForegroundColor Yellow
Write-Host "Tables: $TabCnt" -ForegroundColor Yellow
Write-Host "Table Extensions: $TabExtCnt" -ForegroundColor Yellow
Write-Host "Pages: $PagCnt" -ForegroundColor Yellow
Write-Host "Page Extensions: $PagExtCnt" -ForegroundColor Yellow
Write-Host "Page Customizations: $PagCstmCnt" -ForegroundColor Yellow
Write-Host "Reports: $RepCnt" -ForegroundColor Yellow
Write-Host "Codeunits: $CodCnt" -ForegroundColor Yellow
Write-Host "XMLPorts: $XMLCnt" -ForegroundColor Yellow
Write-Host "Queries: $QueCnt" -ForegroundColor Yellow
Write-Host "Enums: $EnumCnt" -ForegroundColor Yellow
Write-Host "Enum Extensions: $EnumExtCnt" -ForegroundColor Yellow
Write-Host "Keys: $KeysCnt" -ForegroundColor Yellow
Write-Host "ControlAddin: $CtrlAddinCnt" -ForegroundColor Yellow
Write-Host "Dotnet: $DotnetCnt" -ForegroundColor Yellow
Write-Host "Profiles: $ProfileCnt" -ForegroundColor Yellow
$sr.Close()
$sr.Dispose()
$sw.close()
$sw.Dispose()
Invoke-item "$WorkingFolder\SPLITBCOBJ\"
}
Split-ALObjectFile
AL-Pakete lassen sich so erzeugen (hier als Beispiel in C:\Temp)
- Code: Alles auswählen
$WorkingFolder = 'C:\Temp'
Get-Content $WorkingFolder\*.al -encoding UTF8 | Out-File $WorkingFolder\allobjects.al -encoding UTF8