Skip to content

Instantly share code, notes, and snippets.

@altbodhi
Created September 2, 2025 04:21
Show Gist options
  • Select an option

  • Save altbodhi/8725ab50192b280b3e893584df4984f9 to your computer and use it in GitHub Desktop.

Select an option

Save altbodhi/8725ab50192b280b3e893584df4984f9 to your computer and use it in GitHub Desktop.
Парсер выписки по счету из приложения Сбер Онлайн (pdf)
#r "nuget: FSharp.Data"
open FSharp.Data
open System
type AccountTransaction =
{ Date: DateTime
Category: string
Amount: decimal
Description: string }
[<Literal>]
let end_mark = "****0000" // ! <- исправить на цифры из pdf (номер карты)
(*
запросить выписку в сбер онлайн
открыть в Libre Office Draw и
сохранить как fodg под именем sber.fodg в папку с этим скриптом
запустить скрипт командой dotnet fsi SberAccountParser.fsx
(скачать среду NET можно по адресу https://dot.net)
открыть полученный файл transactions.csv в Libre Calc
*)
type AccountStatementOpenDocument = XmlProvider<"sber.fodg">
let doc = AccountStatementOpenDocument.GetSample()
let text =
query {
for page in doc.Body.Drawing.Pages do
for frame in page.Frames do
let item =
match frame.TextBox with
| Some t -> t.P.XElement.Value
| None -> ""
yield item
}
|> Seq.filter (String.IsNullOrWhiteSpace >> not)
|> Seq.reduce (fun x e -> x + ";" + e)
let items = text.Split end_mark
let dec (s: string) =
match Decimal.TryParse s with
| true, v -> if s.StartsWith "+" then Ok v else Ok -v
| _ -> Error $"<{s}> not number"
let parse_desc (s: string) =
let items = s.Split " Операция"
items[0].Trim()
let parse (s: string) =
let terms = s.Split(";", StringSplitOptions.RemoveEmptyEntries)
let zero = terms[0]
match DateTime.TryParse zero with
| true, v ->
let name = terms[3]
match dec terms[4] with
| Ok amount ->
Ok
{ Date = v
Amount = amount
Category = name
Description = parse_desc terms[7] }
| Error e -> Error e
| _ -> Error $"<{zero}> not datetime"
let transactions =
items |> Array.map parse |> Array.filter _.IsOk |> Array.map (fun (Ok tx) -> tx)
let save_as_csv (items: array<AccountTransaction>) path =
let lines = Array.create<string> (items.Length + 1) ""
lines.[0] <- "Год;Месяц;Дата;Операция;Сумма;Категория"
for i = 0 to items.Length - 1 do
let e = items[i]
lines[i + 1] <-
$"""{e.Date.Year};{e.Date.ToString("MMMM")};{e.Date.ToString "yyyy-MM-dd"};{e.Description};{e.Amount};{e.Category}"""
IO.File.WriteAllLines(path, lines)
let card_num = end_mark.Replace("*","")
save_as_csv transactions (IO.Path.Combine(__SOURCE_DIRECTORY__, $"transactions_{card_num}.csv"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment