Skip to content

Commit e6609db

Browse files
authored
Initial Commit
Initial commit of all files
1 parent a77acea commit e6609db

9 files changed

Lines changed: 1381 additions & 2 deletions

File tree

AP_Files.py

Lines changed: 402 additions & 0 deletions
Large diffs are not rendered by default.

AR_Files.py

Lines changed: 444 additions & 0 deletions
Large diffs are not rendered by default.

GP Export Extraction.spec

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# -*- mode: python ; coding: utf-8 -*-
2+
3+
4+
a = Analysis(
5+
['main.py'],
6+
pathex=[],
7+
binaries=[],
8+
datas=[('icon.ico', '.'), ('icon.png', '.'), ('dancing.gif', '.')],
9+
hiddenimports=['AR_Files', 'AP_Files'],
10+
hookspath=[],
11+
hooksconfig={},
12+
runtime_hooks=[],
13+
excludes=[],
14+
noarchive=False,
15+
optimize=0,
16+
)
17+
pyz = PYZ(a.pure)
18+
19+
exe = EXE(
20+
pyz,
21+
a.scripts,
22+
a.binaries,
23+
a.datas,
24+
[],
25+
name='GP Export Extraction',
26+
debug=False,
27+
bootloader_ignore_signals=False,
28+
strip=False,
29+
upx=True,
30+
upx_exclude=[],
31+
runtime_tmpdir=None,
32+
console=False,
33+
disable_windowed_traceback=False,
34+
argv_emulation=False,
35+
target_arch=None,
36+
codesign_identity=None,
37+
entitlements_file=None,
38+
icon=['icon.ico'],
39+
)

README.md

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,102 @@
1-
# Dynamics-GP-AR-AP-Exporter-Parser
2-
A small python app to parse AP/AR PDFs exported out of Dynamics GP
1+
# GP Export Extraction
2+
3+
A small Windows desktop utility to extract data from GP (Dynamics GP) Aged AR/AP report PDFs into a formatted Excel file. It provides a simple GUI to choose AR or AP mode, select a PDF, and generates an Excel file next to the source PDF.
4+
5+
- App: GUI built with Tkinter (no console window)
6+
- Build: PyInstaller (spec file included)
7+
- Target users: finance/accounting teams exporting AR/AP PDFs from GP
8+
9+
10+
## Features
11+
- AR mode (Aged AR Listing-style PDFs)
12+
- Parses customer, document details, dates, and amounts
13+
- Exports formatted Excel with currency formatting and a totals row
14+
- Output file name: <BaseName>_Parsed.xlsx (note capital P)
15+
- If the output Excel is locked/in use, saves with a numeric suffix (e.g., _Parsed_v1.xlsx)
16+
- AP mode (Aged AP Summary by Vendor-style PDFs)
17+
- Parses vendor, payment method, voucher counts, totals and aging buckets
18+
- Exports formatted Excel with currency formatting and a totals row
19+
- Output file name: <BaseName>_parsed.xlsx (note lowercase p)
20+
- Friendly UI: choose AR/AP, select PDF, and see a completion dialog with row count and a small animation
21+
22+
23+
## Getting Started (Run from source)
24+
1. Install Python 3.10+ for Windows (recommended) and ensure “py”/“python” is on PATH.
25+
2. Install dependencies:
26+
- pip install pdfplumber pandas xlsxwriter openpyxl pillow
27+
3. Run the app:
28+
- py main.py
29+
- Select AR or AP, click “Select PDF”, then choose the report PDF exported from GP.
30+
4. Find the output Excel in the same folder as the PDF:
31+
- AR: <BaseName>_Parsed.xlsx
32+
- AP: <BaseName>_parsed.xlsx
33+
34+
Notes
35+
- If Excel reports are open/locked, AR mode automatically retries with _vN suffix.
36+
- The app attempts to detect dates and apply reasonable aging bucket logic; PDFs with significantly different layouts may parse less accurately.
37+
38+
39+
## Using the Packaged EXE
40+
- If you have a packaged build (dist/GP Export Extraction.exe or a Release zip), just double-click the EXE.
41+
- No Python installation required on the target machine.
42+
43+
44+
## Build and Release
45+
Two ways to build with PyInstaller:
46+
47+
A) Using the provided spec file (recommended)
48+
- py -m PyInstaller "GP Export Extraction.spec"
49+
50+
B) One-off command example (for reference; main.py header shows options)
51+
- py -m PyInstaller --onefile --windowed --name "GP Export Extraction" --icon "icon.ico" \
52+
--hidden-import AR_Files --hidden-import AP_Files \
53+
--add-data "icon.ico;." --add-data "icon.png;." --add-data "dancing.gif;." main.py
54+
55+
Automated build script (preferred on Windows)
56+
- The repository includes build.ps1 to build and package a zip for distribution.
57+
- Examples:
58+
- powershell -ExecutionPolicy Bypass -File .\build.ps1
59+
- powershell -ExecutionPolicy Bypass -File .\build.ps1 -Version 1.0.0 -Clean
60+
- Output:
61+
- dist/GP Export Extraction.exe (or onedir variant)
62+
- release/GP-Export-Extraction-<Version>-win.zip (upload this in a GitHub Release)
63+
64+
65+
## Files of Interest
66+
- main.py — Tkinter GUI launcher.
67+
- AR_Files.py — AR parsing/export logic.
68+
- AP_Files.py — AP parsing/export logic.
69+
- GP Export Extraction.spec — PyInstaller spec (includes icons and GIF in the bundle).
70+
- build.ps1 — Windows build/packaging script.
71+
- icon.ico, icon.png — app icons.
72+
73+
74+
## Requirements
75+
- Windows 10/11.
76+
- For running from source:
77+
- Python 3.10+ (Tkinter included with standard CPython installs on Windows)
78+
- Packages: pdfplumber, pandas, xlsxwriter (optional but preferred), openpyxl (fallback), pillow (for GIF decoding; optional)
79+
- For running the EXE: no additional dependencies.
80+
81+
82+
## Troubleshooting
83+
- “pyinstaller not found” when running build.ps1: Install with pip install pyinstaller, or ensure Python Scripts directory is on PATH. The script will try python -m PyInstaller if pyinstaller isn’t on PATH.
84+
- Output Excel won’t save due to file lock: Close the target Excel file and retry; AR mode also attempts _vN filenames automatically.
85+
- Parsing accuracy: These scripts rely on text extraction from PDFs via pdfplumber. If your report layout is different (headers/columns vary), results may need validation. Consider sharing a sample layout for adjustment.
86+
- No dancing.gif or icons in dialogs when running from source: Ensure the working directory contains icon.ico, icon.png, and dancing.gif (PyInstaller bundles these automatically in the EXE build).
87+
88+
89+
## Privacy & Data Handling
90+
- PDFs are processed locally; no data leaves your machine.
91+
- Output files are created in the same directory as the input PDF.
92+
93+
94+
## Changelog
95+
- v1.0.0 (2025-08-15)
96+
- Initial public/internal release with AR/AP parsing and Excel export
97+
- GUI with AR/AP selection and success dialog
98+
- PyInstaller spec and Windows build script (build.ps1)
99+
100+
101+
## License / Usage
102+
- Internal company use only.

build.ps1

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
param(
2+
[string]$Version = "1.0.0",
3+
[switch]$Clean
4+
)
5+
6+
# Build script for GP Export Extraction
7+
# Usage examples:
8+
# powershell -ExecutionPolicy Bypass -File .\build.ps1
9+
# powershell -ExecutionPolicy Bypass -File .\build.ps1 -Version 1.0.0 -Clean
10+
11+
$ErrorActionPreference = 'Stop'
12+
13+
function Write-Section($msg) {
14+
Write-Host "`n=== $msg ===" -ForegroundColor Cyan
15+
}
16+
17+
# Resolve important paths
18+
$RepoRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
19+
Set-Location $RepoRoot
20+
$SpecFile = Join-Path $RepoRoot 'GP Export Extraction.spec'
21+
$DistDir = Join-Path $RepoRoot 'dist'
22+
$BuildDir = Join-Path $RepoRoot 'build'
23+
$ReleaseDir = Join-Path $RepoRoot 'release'
24+
25+
if (!(Test-Path $SpecFile)) {
26+
throw "Spec file not found: $SpecFile"
27+
}
28+
29+
Write-Section "Preparing directories"
30+
if ($Clean) {
31+
if (Test-Path $DistDir) { Remove-Item -Recurse -Force $DistDir }
32+
if (Test-Path $BuildDir) { Remove-Item -Recurse -Force $BuildDir }
33+
}
34+
if (!(Test-Path $ReleaseDir)) { New-Item -ItemType Directory -Path $ReleaseDir | Out-Null }
35+
36+
Write-Section "Locating PyInstaller"
37+
$pyinstallerCmd = Get-Command pyinstaller -ErrorAction SilentlyContinue
38+
if ($null -eq $pyinstallerCmd) {
39+
Write-Host "'pyinstaller' not found on PATH. Will try 'python -m PyInstaller'." -ForegroundColor Yellow
40+
}
41+
42+
Write-Section "Building executable via PyInstaller"
43+
$buildArgs = @('--clean', '"GP Export Extraction.spec"')
44+
try {
45+
if ($pyinstallerCmd) {
46+
& pyinstaller --clean "GP Export Extraction.spec"
47+
} else {
48+
& python -m PyInstaller --clean "GP Export Extraction.spec"
49+
}
50+
} catch {
51+
throw "PyInstaller build failed: $($_.Exception.Message)"
52+
}
53+
54+
Write-Section "Verifying build output"
55+
$onefileExe = Join-Path $DistDir 'GP Export Extraction.exe'
56+
$onedirDir = Join-Path $DistDir 'GP Export Extraction'
57+
58+
if (Test-Path $onefileExe) {
59+
$artifactPath = $onefileExe
60+
$artifactType = 'onefile'
61+
} elseif (Test-Path $onedirDir) {
62+
$artifactPath = $onedirDir
63+
$artifactType = 'onedir'
64+
} else {
65+
throw "Expected output not found in 'dist'. Neither onefile exe nor onedir folder exists."
66+
}
67+
68+
Write-Host "Detected artifact type: $artifactType at $artifactPath" -ForegroundColor Green
69+
70+
# Create a versioned ZIP for release uploads
71+
$zipName = "GP-Export-Extraction-$Version-win.zip"
72+
$zipPath = Join-Path $ReleaseDir $zipName
73+
if (Test-Path $zipPath) { Remove-Item -Force $zipPath }
74+
75+
Write-Section "Packaging release: $zipName"
76+
if ($artifactType -eq 'onefile') {
77+
Compress-Archive -Path $artifactPath -DestinationPath $zipPath
78+
} else {
79+
# Include entire onedir folder contents
80+
Compress-Archive -Path (Join-Path $artifactPath '*') -DestinationPath $zipPath
81+
}
82+
83+
Write-Section "Build complete"
84+
Write-Host "Executable/Folder: $artifactPath" -ForegroundColor Green
85+
Write-Host "Release ZIP: $zipPath" -ForegroundColor Green
86+
Write-Host "Next steps:" -ForegroundColor Cyan
87+
Write-Host " 1) Commit changes and push to GitHub." -ForegroundColor Gray
88+
Write-Host " 2) Tag the repo: git tag v$Version; git push origin v$Version" -ForegroundColor Gray
89+
Write-Host " 3) Create a GitHub Release 'v$Version' and upload: $zipPath" -ForegroundColor Gray

dancing.gif

1.16 MB
Loading

icon.ico

42.3 KB
Binary file not shown.

icon.png

42.3 KB
Loading

0 commit comments

Comments
 (0)