Skip to content

Instantly share code, notes, and snippets.

@user8446
Last active January 6, 2022 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save user8446/dc2bc838d2f8d15aa2d3f3e407a0ce0d to your computer and use it in GitHub Desktop.
Save user8446/dc2bc838d2f8d15aa2d3f3e407a0ce0d to your computer and use it in GitHub Desktop.
GnuCash Process Receipts
#Window title
$host.ui.RawUI.WindowTitle = "GnuCash Process Receipts"
############################
#GnuCash settings: Register > Enable both "Enter moves to blank transaction" & "tab order includes transfer on memorised transactions"
############################
#Load credentials
$KEEPASSVAULT_PW = (Import-Clixml -Path "C:\*******\KeePassVaultCredentials.xml").Password
Unlock-SecretVault -Name KeePassVault -Password $KEEPASSVAULT_PW
$APIKEY = (Get-Secret "TAGGUN").GetNetworkCredential().Password
$FLAGS = Import-Clixml -Path "C:\********\GnuCash Receipt Flags.xml"
$TODAYS_DATE = Get-Date -Format M-d-yy_HH-mm
$YEAR = Get-Date -Format yyyy
#Add for SendKeys & Clear Clipboard
Add-Type -AssemblyName System.Windows.Forms
############################
function GET-RECEIPT {
#Start designated file in GnuCash & wait to open
Start-Process "C:\******\$FOLDER\$FILE"
$TIMEOUT = 45
$TIMER = [Diagnostics.Stopwatch]::StartNew()
do {
Start-Sleep -Milliseconds 500
} until ( ((Get-Process -Name gnucash).MainWindowTitle -like "*GnuCash*") -or ($TIMER.Elapsed.TotalSeconds -gt $TIMEOUT) )
$TIMER.Stop()
if ($TIMER.Elapsed.TotalSeconds -gt $TIMEOUT) {
#Update & save receipt flags
$FLAGS | Export-Clixml -Path "C:\*******\GnuCash Receipt Flags.xml"
$TIME = Get-Date -Format "mm-ss"
"Timeout on GnuCash starting - $FOLDER" | Out-File -FilePath "C:\******\GnuCash Process Receipts-$TIME.txt"
Get-Process -Name gnucash | ForEach-Object { $_.CloseMainWindow() }
exit
}
############################
#Verify GnuCash is on the register tab
if ( (Get-Process -Name gnucash).MainWindowTitle -notlike "*$ACCOUNT*" ) {
#Update & save receipt flags
$FLAGS | Export-Clixml -Path "C:\**********\GnuCash Receipt Flags.xml"
$TIME = Get-Date -Format "mm-ss"
"GnuCash is not on register tab - $FOLDER" | Out-File -FilePath "C:\********\GnuCash Process Receipts-$TIME.txt"
Get-Process -Name gnucash | ForEach-Object { $_.CloseMainWindow() }
exit
}
############################
#Click enter to go to blank transaction & post scheduled transactions
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
############################
#Count for receipt flags
$global:COUNT = 0
Get-ChildItem "C:\******\$PRINTER_FOLDER\*.pdf" |
ForEach-Object {
############################
#TAGGUN API call
$RESPONSE = Invoke-RestMethod -TimeoutSec 40 -RetryIntervalSec 5 -MaximumRetryCount 3 -Method Post `
-Uri "https://api.taggun.io/api/receipt/v1/simple/file" `
-Headers @{ apikey = "$APIKEY" } `
-Form @{ file = [system.io.fileinfo]"$_"; incognito = "true"; language = "en" }
$DATE = $RESPONSE.date.data | Get-Date -Format M/d/yy -ErrorAction Ignore
$DESCRIPTION = $RESPONSE.merchantName.data -replace "[^\d+a-z+\s+&',.!-]"
$TOTAL = $RESPONSE.totalAmount.data
############################
#PDF's greater than 250k try to compress using ImageMagick & ImDisk ramdisk (reports 10k higher so 260000)
if ( (Get-Item -LiteralPath "$_").Length -gt (260000) ) {
magick.exe -density 168x168 -quality 76 -compress JPEG "$_" "R:\$($_.Name)"
#Check if compression succeeded, otherwise keep original
if ( (Get-Item -LiteralPath "$_").Length -gt (Get-Item -LiteralPath "R:\$($_.Name)").Length ) {
#Keep compressed verison
Copy-Item -LiteralPath "R:\$($_.Name)" -Destination $_ -Force
Remove-Item -LiteralPath "R:\$($_.Name)"
}
else {
#Keep original
Remove-Item -LiteralPath "R:\$($_.Name)"
}
}
############################
##Move file to coresponding GnuCash receipt folder, & rename to date-time
#Count for receipt flags
$global:COUNT ++
$_ | Move-Item -Destination "C:\********\$FOLDER\$YEAR"
Rename-Item -LiteralPath "C:\*********\$FOLDER\$YEAR\$($_.Name)" -NewName ("$TODAYS_DATE($COUNT)" + $_.Extension)
############################
## Enter data into GnuCash
#Enter transaction date
[System.Windows.Forms.SendKeys]::SendWait("($DATE)")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
Start-Sleep -Milliseconds 300
#Enter transaction description & amount
[System.Windows.Forms.SendKeys]::SendWait("($DESCRIPTION)")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("($TOTAL)")
Start-Sleep -Milliseconds 300
#Open manage document link - ALT-n, letter m (Transaction menu > Manage document link)
[System.Windows.Forms.SendKeys]::SendWait("%n")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("(m)")
Start-Sleep -Milliseconds 300
#Click linked location in manage document link window
[System.Windows.Forms.SendKeys]::SendWait("{RIGHT}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
#Enter filepath for receipt
Start-Sleep -Milliseconds 300
#[System.Windows.Forms.SendKeys]::SendWait("(file://C:\**********\$FOLDER\$YEAR\$TODAYS_DATE){(}($COUNT){)}$($_.Extension)")
Set-Clipboard -Value "file://C:\********\$FOLDER\$YEAR\$TODAYS_DATE($COUNT)$($_.Extension)"
[System.Windows.Forms.SendKeys]::SendWait("^v")
#Click OK on manage document link window - x2 shift-tab, enter
Start-Sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait("+{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("+{TAB}")
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
#Enter to save and to goto blank transaction
Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
############################
#Clear Variables for next iteration
Clear-Variable DATE -ErrorAction SilentlyContinue
Clear-Variable DESCRIPTION -ErrorAction SilentlyContinue
Clear-Variable TOTAL -ErrorAction SilentlyContinue
}
############################
# Close GnuCash correctly by window so file saves
Start-Sleep -Milliseconds 500
Get-Process -Name gnucash | ForEach-Object { $_.CloseMainWindow() } | Out-Null
############################
#Wait for GnuCash to close
$TIMEOUT = 45
$TIMER = [Diagnostics.Stopwatch]::StartNew()
do {
Start-Sleep -Milliseconds 500
} until ( -not(Get-Process -Name gnucash -ErrorAction Ignore) -or ($TIMER.Elapsed.TotalSeconds -gt $TIMEOUT) )
$TIMER.Stop()
if ($TIMER.Elapsed.TotalSeconds -gt $TIMEOUT) {
#Update & save receipt flags & log error
$FLAGS | Export-Clixml -Path "C:\*********\GnuCash Receipt Flags.xml"
"Timeout on GnuCash wait to close, $FOLDER, $TODAYS_DATE($COUNT)$($_.Extension)" | Out-File -FilePath "C:\*******\GnuCash Process Receipts-$TIME.txt"
Get-Process -Name gnucash | ForEach-Object { $_.CloseMainWindow() }
exit
}
} #### End of GET-RECEIPT fucntion ####
############################
##Check all books for receipts
if (Test-Path -Path "C:\******\*.pdf") {
$PRINTER_FOLDER = "PrinterGnuCash-AI"
$FOLDER = "*****"
$FILE = "*******.gnucash"
$ACCOUNT = "******"
GET-RECEIPT
$FLAGS.******* += $COUNT
}
if (Test-Path -Path "C:\*************\*.pdf") {
$PRINTER_FOLDER = "PrinterGnuCash-AM\*******"
$FOLDER = "*******"
$FILE = "******.gnucash"
$ACCOUNT = "********"
GET-RECEIPT
$FLAGS.****** += $COUNT
}
if (Test-Path -Path "C:\*********\*.pdf") {
$PRINTER_FOLDER = "PrinterGnuCash-AM\******"
$FOLDER = "*******"
$FILE = "********"
$ACCOUNT = "*********"
GET-RECEIPT
$FLAGS.******* += $COUNT
}
if (Test-Path -Path "C:\********\*.pdf") {
$PRINTER_FOLDER = "PrinterGnuCash-AM\******"
$FOLDER = "*****"
$FILE = "*****"
$ACCOUNT = "********"
GET-RECEIPT
$FLAGS.******* += $COUNT
}
# --snip --
############################
#If receipts processed - baloon notification & update receipt flags
if ($COUNT -gt 0) {
#Mute Audio
Add-Type -Language Csharp -TypeDefinition @'
using System.Runtime.InteropServices;
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
// f(), g(), ... are unused COM method slots. Define these if you care
int f(); int g(); int h(); int i();
int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(out float pfLevel);
int k(); int l(); int m(); int n();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
int f(); // Unused
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
public class Audio {
static IAudioEndpointVolume Vol() {
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDevice dev = null;
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
IAudioEndpointVolume epv = null;
var epvid = typeof(IAudioEndpointVolume).GUID;
Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
return epv;
}
public static float Volume {
get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
}
public static bool Mute {
get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
}
}
'@
[Audio]::Mute = $true
############################
#Baloon notification
Add-Type -AssemblyName System.Windows.Forms
$global:balloon = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -Id $pid).Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balloon.BalloonTipText = ' '
$balloon.BalloonTipTitle = "GnuCash receipts processed"
$balloon.Visible = $true
$balloon.ShowBalloonTip(5000)
############################
#Update & save receipt flags
$FLAGS | Export-Clixml -Path "C:\******\GnuCash Receipt Flags.xml"
#Clear clipboard
[System.Windows.Forms.Clipboard]::Clear()
############################
#Unmute Audio
Start-Sleep -Seconds 2
[Audio]::Mute = $false
}
############################
#Log errors
if ($ERROR.count -gt 0) {
$TIME = Get-Date -Format "mm-ss"
$ERROR | Out-File -FilePath "C:\********\GnuCash Process Receipts-$TIME.txt"
}
exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment