{"id":38,"date":"2025-12-02T14:10:53","date_gmt":"2025-12-02T13:10:53","guid":{"rendered":"http:\/\/serwer402453.lh.pl\/autoinstalator\/serwer402453.lh.pl\/wordpress143401\/?p=38"},"modified":"2026-05-07T22:22:51","modified_gmt":"2026-05-07T20:22:51","slug":"sap-excel-pdf-web-automation","status":"publish","type":"post","link":"https:\/\/chmielinski-konrad.info\/index.php\/2025\/12\/02\/sap-excel-pdf-web-automation\/","title":{"rendered":"SAP, MS Office, PDF, Web Automation &amp; more"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"pl\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>SAP, MS Office, PDF, Web Automation &amp; more &mdash; Konrad Chmielinski<\/title>\n    <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n    <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n    <link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=JetBrains+Mono:wght@400;500;700&#038;family=Sora:wght@300;400;600;700&#038;display=swap\" media=\"print\" onload=\"this.media='all'\">\n    <noscript>\n        <link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=JetBrains+Mono:wght@400;500;700&#038;family=Sora:wght@300;400;600;700&#038;display=swap\">\n    <\/noscript>\n    <style>\n    :root {\n        --accent: #D97706;\n        --accent-dim: #B45309;\n        --accent-bg: #FEF3C7;\n        --mono: 'JetBrains Mono', monospace;\n        --sans: 'Sora', sans-serif;\n    }\n\n    * {\n        box-sizing: border-box;\n        margin: 0;\n        padding: 0;\n    }\n\n    body {\n        background: #fff;\n        color: #111;\n        -webkit-overflow-scrolling: touch;\n        overflow-x: hidden;\n    }\n\n    .blog-root {\n        font-family: var(--sans);\n        color: #111;\n        max-width: 100%;\n        margin: 0 auto;\n        padding: 2rem 1rem 4rem;\n        line-height: 1.7;\n    }\n\n    .eyebrow {\n        font-family: var(--mono);\n        font-size: 11px;\n        letter-spacing: .12em;\n        color: var(--accent-dim);\n        text-transform: uppercase;\n        margin-bottom: .75rem;\n        display: flex;\n        align-items: center;\n        gap: 8px;\n    }\n\n    .eyebrow::before {\n        content: '';\n        display: inline-block;\n        width: 24px;\n        height: 1.5px;\n        background: var(--accent);\n    }\n\n    h1.blog-title {\n        font-family: var(--sans);\n        font-size: 2.2rem;\n        font-weight: 700;\n        line-height: 1.2;\n        margin-bottom: .5rem;\n        color: #111;\n    }\n\n    .subtitle {\n        font-size: 1.05rem;\n        color: #555;\n        font-weight: 300;\n        margin-bottom: 1.75rem;\n    }\n\n    .meta-row {\n        display: flex;\n        align-items: center;\n        gap: 1rem;\n        padding: .75rem 0;\n        border-top: .5px solid #ddd;\n        border-bottom: .5px solid #ddd;\n        margin-bottom: 2rem;\n        flex-wrap: wrap;\n    }\n\n    .meta-chip {\n        font-family: var(--mono);\n        font-size: 11px;\n        background: #f4f4f2;\n        border: .5px solid #ddd;\n        border-radius: 4px;\n        padding: 3px 8px;\n        color: #555;\n    }\n\n    .meta-chip.amber {\n        background: var(--accent-bg);\n        color: var(--accent-dim);\n        border-color: #FCD34D;\n    }\n\n    .tech-grid {\n        display: grid;\n        grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n        gap: 10px;\n        margin: 1.5rem 0 2rem;\n    }\n\n    .tech-card {\n        background: #fff;\n        border: .5px solid #ddd;\n        border-radius: 12px;\n        padding: .875rem 1rem;\n        position: relative;\n    }\n\n    .tech-card .tc-label {\n        font-family: var(--mono);\n        font-size: 10px;\n        color: #777;\n        letter-spacing: .08em;\n        text-transform: uppercase;\n        margin-bottom: 4px;\n    }\n\n    .tech-card .tc-name {\n        font-size: 14px;\n        font-weight: 600;\n        color: #111;\n        margin-bottom: 4px;\n    }\n\n    .tech-card .tc-note {\n        font-size: 12px;\n        color: #555;\n        line-height: 1.4;\n    }\n\n    .tech-card .tc-dot {\n        position: absolute;\n        top: 12px;\n        right: 12px;\n        width: 7px;\n        height: 7px;\n        border-radius: 50%;\n        background: var(--accent);\n    }\n\n    .section-header {\n        display: flex;\n        align-items: center;\n        gap: 10px;\n        margin: 2.25rem 0 1rem;\n    }\n\n    .section-header h2 {\n        font-family: var(--sans);\n        font-size: 1.15rem;\n        font-weight: 600;\n        color: #111;\n    }\n\n    .sh-line {\n        flex: 1;\n        height: .5px;\n        background: #ddd;\n    }\n\n    .sh-badge {\n        font-family: var(--mono);\n        font-size: 10px;\n        background: var(--accent-bg);\n        color: var(--accent-dim);\n        border-radius: 4px;\n        padding: 2px 8px;\n        white-space: nowrap;\n        border: .5px solid #FCD34D;\n    }\n\n    p.body {\n        font-size: 15px;\n        color: #111;\n        margin-bottom: 1rem;\n    }\n\n    .pipeline-visual {\n        background: #f7f7f5;\n        border: .5px solid #ddd;\n        border-radius: 12px;\n        padding: 1.25rem 1.5rem;\n        margin: 1.5rem 0;\n        overflow-x: auto;\n        -webkit-overflow-scrolling: touch;\n        touch-action: pan-x pan-y;\n    }\n\n    .pipeline-row {\n        display: flex;\n        align-items: center;\n        gap: 8px;\n        flex-wrap: nowrap;\n    }\n\n    .pipeline-col {\n        display: flex;\n        flex-direction: column;\n        gap: 4px;\n        align-items: center;\n    }\n\n    .pipe-step {\n        background: #fff;\n        border: .5px solid #ddd;\n        border-radius: 6px;\n        padding: 6px 12px;\n        font-family: var(--mono);\n        font-size: 11px;\n        color: #111;\n        white-space: nowrap;\n        font-weight: 500;\n    }\n\n    .pipe-step.hl {\n        background: var(--accent-bg);\n        border-color: #FCD34D;\n        color: var(--accent-dim);\n    }\n\n    .pipe-label {\n        font-family: var(--mono);\n        font-size: 9px;\n        color: #aaa;\n        text-transform: uppercase;\n        letter-spacing: .06em;\n        text-align: center;\n    }\n\n    .pipe-arrow {\n        color: #999;\n        font-size: 12px;\n        flex-shrink: 0;\n    }\n\n    .code-block {\n        background: #f7f7f5;\n        border: .5px solid #ddd;\n        border-left: 2.5px solid var(--accent);\n        border-radius: 0 8px 8px 0;\n        padding: 1rem 1.25rem;\n        margin: 1rem 0 1.5rem;\n        font-family: var(--mono);\n        font-size: 12px;\n        color: #555;\n        line-height: 1.65;\n        overflow-x: auto;\n    }\n\n    .code-block .kw {\n        color: #D97706;\n        font-weight: 500;\n    }\n\n    .code-block .str {\n        color: #BA7517;\n    }\n\n    .code-block .cmt {\n        color: #aaa;\n    }\n\n    .tag-cloud {\n        display: flex;\n        flex-wrap: wrap;\n        gap: 6px;\n        margin: 1rem 0 1.5rem;\n    }\n\n    .tag {\n        font-family: var(--mono);\n        font-size: 11px;\n        padding: 4px 10px;\n        border-radius: 100px;\n        border: .5px solid #ccc;\n        color: #555;\n        background: #fff;\n    }\n\n    .tag.primary {\n        background: var(--accent-bg);\n        border-color: #FCD34D;\n        color: var(--accent-dim);\n        font-weight: 500;\n    }\n\n    .callout {\n        background: #f7f7f5;\n        border-left: 2px solid var(--accent);\n        border-radius: 0 8px 8px 0;\n        padding: 1rem 1.25rem;\n        margin: 1.5rem 0;\n        font-size: 14px;\n        color: #555;\n        line-height: 1.65;\n    }\n\n    .callout strong {\n        color: #111;\n        font-weight: 600;\n    }\n\n    .platform-table {\n        width: 100%;\n        border-collapse: collapse;\n        font-size: 13px;\n        margin: 1.5rem 0;\n    }\n\n    .platform-table th {\n        font-family: var(--mono);\n        font-size: 10px;\n        letter-spacing: .08em;\n        text-transform: uppercase;\n        color: #777;\n        font-weight: 500;\n        padding: 8px 12px;\n        border-bottom: .5px solid #ddd;\n        text-align: left;\n    }\n\n    .platform-table td {\n        padding: 8px 12px;\n        border-bottom: .5px solid #f0f0f0;\n        color: #555;\n        vertical-align: top;\n    }\n\n    .platform-table td:first-child {\n        font-weight: 600;\n        color: #111;\n        white-space: nowrap;\n    }\n\n    .platform-table tr:last-child td {\n        border-bottom: none;\n    }\n\n    .footer-note {\n        font-family: var(--mono);\n        font-size: 11px;\n        color: #777;\n        border-top: .5px solid #ddd;\n        margin-top: 3rem;\n        padding-top: 1rem;\n        display: flex;\n        justify-content: space-between;\n        flex-wrap: wrap;\n        gap: 4px;\n    }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"blog-root\">\n\n        <div class=\"eyebrow\">Engineering Blog &middot; Konrad Chmielinski<\/div>\n        <p class=\"subtitle\">End-to-end process automation across every surface an enterprise runs on &mdash; from SAP transactions and Excel workbooks to email workflows and web portals.<\/p>\n\n        <div class=\"meta-row\">\n            <span class=\"meta-chip amber\">RPA Engineering<\/span>\n            <span class=\"meta-chip\">SAP &middot; Excel &middot; PDF &middot; Email<\/span>\n            <span class=\"meta-chip\">AA A360 &middot; Python &middot; Selenium<\/span>\n            <span class=\"meta-chip\">Katowice, PL &middot; Remote OK<\/span>\n        <\/div>\n\n        <p class=\"body\">Enterprise automation is not about one system &mdash; it is about connecting all of them. A single business process might read data from SAP, consolidate it across Excel workbooks, generate a PDF report, send it by email, and upload the result to a web portal &mdash; all in sequence, all without a human in the loop. Building that chain reliably is the real job.<\/p>\n        <p class=\"body\">Over 4+ years I have built and maintained production automation across every surface type that enterprises actually run on. This post covers the full platform stack in depth &mdash; SAP, MS Office, email, PDF, web, and specialist portals.<\/p>\n\n        <!-- SAP -->\n        <div class=\"section-header\">\n            <h2>SAP automation<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">the enterprise core<\/div>\n        <\/div>\n        <p class=\"body\">SAP is the operational backbone at ArcelorMittal &mdash; HR, finance, procurement, and logistics all live there. Automating SAP means navigating transaction codes, reading and writing field values, executing reports, and handling session state across long-running bot runs. I work with two distinct approaches depending on what access is available.<\/p>\n        <p class=\"body\">\n            <strong>SAP GUI Scripting<\/strong>\n             simulates user interaction at the GUI layer &mdash; opening transactions, filling fields, clicking buttons, reading output screens. It works across all SAP modules without requiring any special access beyond a normal user account. The tradeoff is fragility: screen layouts must be consistent, and session timeouts need explicit recovery logic.\n        <\/p>\n        <p class=\"body\">\n            <strong>PyRFC \/ BAPI calls<\/strong>\n             bypass the GUI entirely and call SAP function modules directly via the Remote Function Call interface. This is significantly faster and more robust for high-volume data operations, but requires RFC access to be granted by SAP basis &mdash; which is not always available. Where it is, I prefer it strongly over GUI scripting.\n        <\/p>\n\n        <div class=\"tech-grid\">\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">GUI layer<\/div>\n                <div class=\"tc-name\">SAP GUI Scripting<\/div>\n                <div class=\"tc-note\">Python-driven session management, transaction navigation, field-level data entry and extraction. Works universally across SAP modules.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Direct calls<\/div>\n                <div class=\"tc-name\">PyRFC \/ BAPI<\/div>\n                <div class=\"tc-note\">Direct SAP function module calls via RFC. Faster and more robust than GUI scripting for bulk data operations.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">RPA layer<\/div>\n                <div class=\"tc-name\">AA A360 SAP package<\/div>\n                <div class=\"tc-note\">Automation Anywhere native SAP actions for complex multi-transaction flows within orchestrated enterprise workflows.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Reporting<\/div>\n                <div class=\"tc-name\">SAP report extraction<\/div>\n                <div class=\"tc-note\">Automated execution of SAP standard and custom reports, extraction to file, and handoff to downstream processing pipelines.<\/div>\n            <\/div>\n        <\/div>\n\n        <div class=\"code-block\">\n            <span class=\"cmt\"># SAP GUI scripting session pattern with timeout recovery<\/span>\n            <br>\n            <span class=\"kw\">import<\/span>\n             win32com.client\n            <br>\n            <br>\n\n                sap = win32com.client.GetObject(\n            <span class=\"str\">&#8220;SAPGUI&#8221;<\/span>\n            )\n            <br>\n\n                app = sap.GetScriptingEngine\n            <br>\n\n                conn = app.Children(0)\n            <br>\n\n                session = conn.Children(0)\n            <br>\n            <br>\n\n                session.findById(\n            <span class=\"str\">&#8220;wnd[0]\/tbar[0]\/okcd&#8221;<\/span>\n            ).text = \n            <span class=\"str\">&#8220;\/nPA30&#8221;<\/span>\n            <br>\n\n                session.findById(\n            <span class=\"str\">&#8220;wnd[0]&#8221;<\/span>\n            ).sendVKey(0)\n            <br>\n            <span class=\"cmt\"># Navigate to HR master data transaction<\/span>\n        <\/div>\n\n        <div class=\"callout\">\n            <strong>At ArcelorMittal (Global HRS):<\/strong>\n             four bots automate HR contract generation &mdash; reading structured data from financial and entity documents, navigating SAP HR transactions, and performing data entry for employee contracts across global business units. Session timeout recovery and transaction error handling are production-critical for overnight unattended runs spanning multiple time zones.\n        <\/div>\n\n        <!-- MS OFFICE -->\n        <div class=\"section-header\">\n            <h2>MS Office &mdash; Excel, Word, Outlook<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">the universal business layer<\/div>\n        <\/div>\n        <p class=\"body\">Regardless of how modern an organisation&rsquo;s core systems are, the business layer almost always runs on Excel, Word, and Outlook. Automating here means handling the full lifecycle of each format &mdash; reading, transforming, generating, and distributing &mdash; often across files that were built incrementally over years with no consistent structure.<\/p>\n\n        <p class=\"body\">\n            <strong>Excel<\/strong>\n             is the most common automation surface I encounter. I work with it at every level: pure Python libraries (openpyxl, xlrd, xlsxwriter) for headless processing, pandas for data transformation and consolidation, and win32com for cases where Excel formulas, pivot tables, or VBA-dependent formatting must be preserved. Multi-sheet workbooks with inconsistent column headers, merged cells, and embedded charts are routine production inputs &mdash; not edge cases.\n        <\/p>\n\n        <div class=\"code-block\">\n            <span class=\"cmt\"># Multi-sheet, multi-file Excel consolidation (AM global forecasting)<\/span>\n            <br>\n            <span class=\"kw\">import<\/span>\n             pandas \n            <span class=\"kw\">as<\/span>\n             pd\n            <br>\n            <span class=\"kw\">from<\/span>\n             pathlib \n            <span class=\"kw\">import<\/span>\n             Path\n            <br>\n            <br>\n\n                frames = []\n            <br>\n            <span class=\"kw\">for<\/span>\n             f \n            <span class=\"kw\">in<\/span>\n             Path(\n            <span class=\"str\">&#8220;bu_reports\/&#8221;<\/span>\n            ).glob(\n            <span class=\"str\">&#8220;*.xlsx&#8221;<\/span>\n            ):\n            <br>\n\n                &nbsp;&nbsp;xls = pd.ExcelFile(f)\n            <br>\n\n                &nbsp;&nbsp;\n            <span class=\"kw\">for<\/span>\n             sheet \n            <span class=\"kw\">in<\/span>\n             xls.sheet_names:\n            <br>\n\n                &nbsp;&nbsp;&nbsp;&nbsp;df = xls.parse(sheet, header=2)\n            <span class=\"cmt\">  # headers not always row 1<\/span>\n            <br>\n\n                &nbsp;&nbsp;&nbsp;&nbsp;df[\n            <span class=\"str\">&#8220;source_unit&#8221;<\/span>\n            ] = f.stem\n            <br>\n\n                &nbsp;&nbsp;&nbsp;&nbsp;frames.append(df)\n            <br>\n\n                master = pd.concat(frames, ignore_index=\n            <span class=\"kw\">True<\/span>\n            )\n              \n        <\/div>\n\n        <p class=\"body\">\n            <strong>Word<\/strong>\n             document generation is a key output layer for HR and compliance workflows. I use python-docx to generate contracts, reports, and formal documents from structured templates &mdash; populating placeholders, inserting tables, and applying consistent formatting. For complex documents that require preserving native Word formatting, win32com drives Word directly.\n        <\/p>\n\n        <div class=\"tag-cloud\">\n            <span class=\"tag primary\">openpyxl<\/span>\n            <span class=\"tag primary\">pandas Excel I\/O<\/span>\n            <span class=\"tag primary\">xlrd \/ xlsxwriter<\/span>\n            <span class=\"tag primary\">win32com (Excel \/ Word)<\/span>\n            <span class=\"tag primary\">python-docx<\/span>\n            <span class=\"tag\">VBA (migration source)<\/span>\n            <span class=\"tag\">AA A360 Excel package<\/span>\n            <span class=\"tag\">Template-based generation<\/span>\n            <span class=\"tag\">Multi-sheet consolidation<\/span>\n            <span class=\"tag\">Pivot table automation<\/span>\n        <\/div>\n\n        <div class=\"callout\">\n            <strong>VBA to Python migration (ArcelorMittal):<\/strong>\n             migrated two legacy VBA bots to Python to comply with new company standards &mdash; reverse-engineering years of undocumented macro logic embedded across multiple modules, rewriting in maintainable Python with proper error handling, and integrating with modern CI\/CD pipelines while preserving identical output for downstream stakeholders.\n        <\/div>\n\n        <!-- EMAIL -->\n        <div class=\"section-header\">\n            <h2>Email automation &mdash; inbound &amp; outbound<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">trigger, parse, respond, dispatch<\/div>\n        <\/div>\n        <p class=\"body\">Email is both a trigger and a delivery mechanism in many enterprise automation workflows. I work with email in both directions &mdash; monitoring inboxes for incoming requests that kick off a process, and dispatching structured output at the end of a pipeline to the right recipients with the right attachments.<\/p>\n\n        <p class=\"body\">\n            <strong>Inbound email processing<\/strong>\n             involves monitoring a shared mailbox, parsing subject lines and body content to classify the request type, extracting attachments for downstream processing, and routing the email to the appropriate workflow branch. At ArcelorMittal Luxembourg, incoming client inquiry emails triggered the entire AI offer generation pipeline &mdash; the bot read the email, retrieved matching historical orders, generated a personalised proposal via GPT-4o, and dispatched the reply automatically.\n        <\/p>\n\n        <p class=\"body\">\n            <strong>Outbound email dispatch<\/strong>\n             is the final step of many pipelines &mdash; sending run summary reports to process owners, distributing generated PDF reports to stakeholders, alerting on exceptions, and delivering automated client responses. I use Microsoft Graph API as the primary email channel (OAuth2, no SMTP credentials required), with win32com Outlook automation as a fallback for on-premise environments.\n        <\/p>\n\n        <div class=\"tech-grid\">\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Primary API<\/div>\n                <div class=\"tc-name\">Microsoft Graph API<\/div>\n                <div class=\"tc-note\">OAuth2-authenticated mail send and receive. Read shared mailboxes, parse attachments, send with attachments. No SMTP credentials needed.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Fallback<\/div>\n                <div class=\"tc-name\">win32com Outlook<\/div>\n                <div class=\"tc-note\">Drive Outlook directly via COM automation for on-premise environments without Graph API access.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Legacy \/ simple<\/div>\n                <div class=\"tc-name\">smtplib \/ imaplib<\/div>\n                <div class=\"tc-note\">Standard Python email libraries for lightweight send\/receive where modern API access is not available.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Parsing<\/div>\n                <div class=\"tc-name\">email \/ mailparser<\/div>\n                <div class=\"tc-note\">Subject, body, and attachment parsing from raw MIME messages. Classification logic to route to correct workflow branch.<\/div>\n            <\/div>\n        <\/div>\n\n        <div class=\"pipeline-visual\">\n            <div class=\"pipeline-row\">\n                <div class=\"pipeline-col\">\n                    <div class=\"pipe-step hl\">Inbox monitor<\/div>\n                    <div class=\"pipe-label\">Graph API poll<\/div>\n                <\/div>\n                <div class=\"pipe-arrow\">&rarr;<\/div>\n                <div class=\"pipeline-col\">\n                    <div class=\"pipe-step\">Parse &amp; classify<\/div>\n                    <div class=\"pipe-label\">subject \/ body \/ attach<\/div>\n                <\/div>\n                <div class=\"pipe-arrow\">&rarr;<\/div>\n                <div class=\"pipeline-col\">\n                    <div class=\"pipe-step hl\">Route<\/div>\n                    <div class=\"pipe-label\">workflow branch<\/div>\n                <\/div>\n                <div class=\"pipe-arrow\">&rarr;<\/div>\n                <div class=\"pipeline-col\">\n                    <div class=\"pipe-step\">Process<\/div>\n                    <div class=\"pipe-label\">pipeline execution<\/div>\n                <\/div>\n                <div class=\"pipe-arrow\">&rarr;<\/div>\n                <div class=\"pipeline-col\">\n                    <div class=\"pipe-step hl\">Dispatch reply<\/div>\n                    <div class=\"pipe-label\">Graph API send<\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <div class=\"callout\">\n            <strong>At ArcelorMittal Luxembourg (AI Offer Generation):<\/strong>\n             the entire pipeline was email-triggered. Incoming client inquiry &rarr; Graph API read &rarr; attachment and body parsing &rarr; historical order retrieval &rarr; GPT-4o inference &rarr; personalised proposal generation &rarr; automated email reply via Graph API. No human in the loop from trigger to dispatch.\n        <\/div>\n\n        <!-- PDF -->\n        <div class=\"section-header\">\n            <h2>PDF automation<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">extraction &amp; generation<\/div>\n        <\/div>\n        <p class=\"body\">\n            PDF automation splits cleanly into two directions. \n            <em>Extraction<\/em>\n             means reading structured data out of existing documents &mdash; research reports, invoices, contracts, identity documents. \n            <em>Generation<\/em>\n             means producing formatted, submission-ready output from data &mdash; compliance reports, HR documents, run summaries.\n        <\/p>\n\n        <div class=\"tech-grid\">\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Extraction<\/div>\n                <div class=\"tc-name\">pdfplumber \/ pdfminer<\/div>\n                <div class=\"tc-note\">Layout-aware text and table extraction from digital PDFs. Used for structured field extraction from research and financial documents.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Extraction<\/div>\n                <div class=\"tc-name\">PyPDF2 \/ pypdf<\/div>\n                <div class=\"tc-note\">Metadata reading, page splitting and merging, lightweight text extraction from machine-readable PDFs.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Generation<\/div>\n                <div class=\"tc-name\">ReportLab \/ FPDF2<\/div>\n                <div class=\"tc-note\">Programmatic PDF generation from structured data. Used for compliance reports, HR documents, and pipeline output summaries.<\/div>\n            <\/div>\n            <div class=\"tech-card\">\n                <div class=\"tc-dot\"><\/div>\n                <div class=\"tc-label\">Scanned PDFs<\/div>\n                <div class=\"tc-name\">Azure OCR + Pillow<\/div>\n                <div class=\"tc-note\">For image-based PDFs: rasterise pages with Pillow, pass to Azure OCR for text extraction before structured processing.<\/div>\n            <\/div>\n        <\/div>\n\n        <!-- WEB + PORTALS -->\n        <div class=\"section-header\">\n            <h2>Web &amp; portal automation<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">portals, scraping, authenticated flows<\/div>\n        <\/div>\n        <p class=\"body\">\n            Web automation covers authenticated internal portals, external data sources, and specialised industry systems. At ING, bots interacted with \n            <strong>IRIS<\/strong>\n             &mdash; a financial security monitoring portal &mdash; loading data, retrieving records, and generating output files for the KYC compliance pipeline. At ArcelorMittal, the compliance reporting workflow automated \n            <strong>SARA<\/strong>\n             and \n            <strong>REX<\/strong>\n            , two workplace safety portals used for collecting incident documentation &mdash; downloading records, uploading processed data, copying information between systems, and generating regulatory report files.\n        <\/p>\n        <p class=\"body\">None of these portals expose a public API. All interaction is engineered through the browser layer using Selenium with explicit wait strategies, session management, and retry logic to handle the inevitable timeouts and page state changes that occur in long unattended runs.<\/p>\n\n        <div class=\"tag-cloud\">\n            <span class=\"tag primary\">Selenium (XPath \/ CSS selectors)<\/span>\n            <span class=\"tag primary\">BeautifulSoup<\/span>\n            <span class=\"tag primary\">Python requests + session handling<\/span>\n            <span class=\"tag\">IRIS (ING financial security portal)<\/span>\n            <span class=\"tag\">SARA (AM safety reporting)<\/span>\n            <span class=\"tag\">REX (AM accident documentation)<\/span>\n            <span class=\"tag\">AA A360 browser actions<\/span>\n            <span class=\"tag\">File download \/ upload automation<\/span>\n            <span class=\"tag\">Explicit wait strategies<\/span>\n            <span class=\"tag\">Session refresh logic<\/span>\n        <\/div>\n\n        <!-- DESKTOP -->\n        <div class=\"section-header\">\n            <h2>Desktop &amp; GUI automation<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">legacy Windows apps<\/div>\n        <\/div>\n        <p class=\"body\">For legacy Windows applications with no web layer and no API, I use UIAutomation (Windows accessibility tree) as the primary approach &mdash; robust to resolution and DPI changes &mdash; with PyAutoGUI as a last resort for applications that expose no accessibility interface. At ING, I built and delivered a GUI bot on SAIO, ING&rsquo;s proprietary RPA platform, and ran training sessions to promote wider team adoption.<\/p>\n\n        <div class=\"tag-cloud\">\n            <span class=\"tag primary\">UIAutomation<\/span>\n            <span class=\"tag primary\">PyAutoGUI<\/span>\n            <span class=\"tag primary\">SAIO (ING proprietary)<\/span>\n            <span class=\"tag\">Automation Anywhere A360<\/span>\n            <span class=\"tag\">Windows accessibility tree<\/span>\n            <span class=\"tag\">Screen element detection<\/span>\n        <\/div>\n\n        <!-- PLATFORM TABLE -->\n        <div class=\"section-header\">\n            <h2>RPA platforms<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">what I use and where<\/div>\n        <\/div>\n        <table class=\"platform-table\">\n            <thead>\n                <tr>\n                    <th>Platform<\/th>\n                    <th>Employer<\/th>\n                    <th>Experience<\/th>\n                    <th>Primary use<\/th>\n                <\/tr>\n            <\/thead>\n            <tbody>\n                <tr>\n                    <td>Automation Anywhere A360<\/td>\n                    <td>ArcelorMittal BCoE<\/td>\n                    <td>2+ years<\/td>\n                    <td>Bot development, orchestration, scheduling, credential vault<\/td>\n                <\/tr>\n                <tr>\n                    <td>Automation Anywhere A11<\/td>\n                    <td>ArcelorMittal BCoE<\/td>\n                    <td>Legacy maintained<\/td>\n                    <td>Legacy bot maintenance and migration to A360<\/td>\n                <\/tr>\n                <tr>\n                    <td>SAIO<\/td>\n                    <td>ING Hubs Poland<\/td>\n                    <td>1+ year<\/td>\n                    <td>GUI bot development, team training, internal process automation<\/td>\n                <\/tr>\n                <tr>\n                    <td>UiPath<\/td>\n                    <td>Certification<\/td>\n                    <td>Foundation certified<\/td>\n                    <td>RPA Developer Foundation v2021.10<\/td>\n                <\/tr>\n                <tr>\n                    <td>Python standalone<\/td>\n                    <td>Both employers<\/td>\n                    <td>5+ years<\/td>\n                    <td>Lightweight bots, ETL scripts, migration target for legacy VBA<\/td>\n                <\/tr>\n            <\/tbody>\n        <\/table>\n\n        <!-- FULL STACK -->\n        <div class=\"section-header\">\n            <h2>Full stack<\/h2>\n            <div class=\"sh-line\"><\/div>\n            <div class=\"sh-badge\">everything I use<\/div>\n        <\/div>\n        <div class=\"tag-cloud\">\n            <span class=\"tag primary\">SAP GUI Scripting<\/span>\n            <span class=\"tag primary\">PyRFC \/ BAPI<\/span>\n            <span class=\"tag primary\">Automation Anywhere A360 \/ A11<\/span>\n            <span class=\"tag primary\">openpyxl \/ pandas \/ xlsxwriter<\/span>\n            <span class=\"tag primary\">python-docx<\/span>\n            <span class=\"tag primary\">Microsoft Graph API<\/span>\n            <span class=\"tag primary\">win32com (Excel \/ Word \/ Outlook)<\/span>\n            <span class=\"tag primary\">Selenium + XPath<\/span>\n            <span class=\"tag primary\">pdfplumber \/ ReportLab<\/span>\n            <span class=\"tag primary\">UIAutomation<\/span>\n            <span class=\"tag primary\">SAIO<\/span>\n            <span class=\"tag\">BeautifulSoup<\/span>\n            <span class=\"tag\">PyAutoGUI<\/span>\n            <span class=\"tag\">smtplib \/ imaplib<\/span>\n            <span class=\"tag\">Azure OCR + Pillow<\/span>\n            <span class=\"tag\">PyPDF2 \/ pypdf<\/span>\n            <span class=\"tag\">FPDF2<\/span>\n            <span class=\"tag\">Jenkins CI\/CD<\/span>\n            <span class=\"tag\">Git<\/span>\n            <span class=\"tag\">Pydantic<\/span>\n        <\/div>\n\n        <div class=\"footer-note\">\n            <span>konrad.chmielinski@outlook.com<\/span>\n            <span>linkedin.com\/in\/konrad-chmielinski<\/span>\n            <span>Open to remote &middot; Full-time \/ B2B<\/span>\n        <\/div>\n\n    <\/div>\n<\/body>\n<\/html>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>SAP, MS Office, PDF, Web Automation &amp; more &mdash; Konrad Chmielinski Engineering Blog &middot; Konrad Chmielinski End-to-end process automation across every surface an enterprise runs on &mdash; from SAP transactions and Excel workbooks to email workflows and web portals. RPA Engineering SAP &middot; Excel &middot; PDF &middot; Email AA A360 &middot; Python &middot; Selenium Katowice, PL &middot; Remote OK Enterprise [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":136,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-38","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-skills"],"views":55,"_links":{"self":[{"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/posts\/38","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/comments?post=38"}],"version-history":[{"count":15,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/posts\/38\/revisions"}],"predecessor-version":[{"id":527,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/posts\/38\/revisions\/527"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/media\/136"}],"wp:attachment":[{"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/media?parent=38"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/categories?post=38"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chmielinski-konrad.info\/index.php\/wp-json\/wp\/v2\/tags?post=38"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}