다음 블로그 게시물에서 보실 수 있듯이 저는 지금 금융 지식의 시대에 살고 있습니다. 연말이 다가옴에 따라 내 수치를 살펴보고 싶었습니다. 내가 낸 세금은 얼마나 됩니까? 당직 교대근무로 얼마를 벌었나요? 여러 PDF 파일은 이 데이터를 보는 가장 편안한 방법이 아니며 Excel에서 사용할 수 있는 단일 CSV 파일을 원했습니다.
많은 훌륭한 개발자들처럼 저도 수동으로 숫자를 입력하기에는 너무 게을러서 스크립트를 작성했습니다. 프로그래밍을 좋아하신다면 저와 함께 모험을 떠나보세요! 기분이 좋지 않다면 급여명세서 구조에 맞게 코드를 조정하는 방법을 알려드리겠습니다. :D
This script receives a directory with payslip PDFs and returns a CSV file with the desired data |
main.py: # translate 1 pdf to 1 dict # loop over the pdf dir # save all dicts to 1 json file # translate json report to csv report
보고서에서 원하는 필드를 결정하는 것을 포함하여 PDF를 읽는 코드를 작성하는 것부터 시작하겠습니다. 급여명세서 구조에 맞게 조정해야 할 부분입니다. 그것이 파악되면 전체 급여명세서 디렉토리를 반복할 것입니다.
세 번째 단계에서는 PDF와 CSV 사이에 JSON 보고서라는 추가 단계를 추가하기로 결정했습니다. 모든 것이 제대로 작동하는 것을 확인하면 해당 파일의 사용을 제거하겠습니다.
마지막으로 해당 JSON 데이터를 CSV 파일로 변환하겠습니다. 그런 다음 해당 CSV를 Google 스프레드시트('다음으로 열기' 클릭) 또는 Excel(지침은 여기에서 찾을 수 있음)로 쉽게 변환할 수 있습니다.
쉽고 좋은 계획이지만 어떻게 진행되는지 아시죠? 그 과정에서 문제가 발견됩니다... 상황이 복잡해질 수 있는 부분이 무엇인지 추측할 수 있나요?
시작하기 전에 중요한 사항: 급여 명세서를 비공개로 유지하세요! 프로젝트를 GitHub에 업로드하는 경우 개인 정보를 공유하지 마세요! 이를 위해 .gitignore를 사용할 수 있습니다:
/payslips_pdf pdf_rows.txt report.json report.csv
시작해볼까요?
먼저 PDF를 읽고 모든 행을 인쇄하겠습니다. 그렇게 하면 각 행에 무엇이 나타나는지 알 수 있습니다. 이 작업은 한 번만 수행하면 되며(보고서는 한 달에 한 번 또는 1년에 한 번 생성됨) 보고서의 일부가 아니므로 별도의 파일로 생성하겠습니다.
새 Python 파일(저는 pdf_to_txt.py라고 함)을 만드는 것으로 시작하고 pdf를 읽고 결과를 .txt 파일로 인쇄하는 함수를 작성합니다.
메인 스크립트에서도 PDF 파일을 읽어드릴 테니 이 기능을 그쪽으로 옮기시면 더 좋습니다.
이제 PDF가 읽혀지는 구조를 알았으므로 원하는 값을 낚시할 수 있습니다. 제 경우에는 제가 관심을 보인 정보는 다음과 같습니다.
표 내부에는 데이터(매월 달라질 수 있는 카테고리)가 있고 표 외부에는 데이터가 있습니다.
테이블 외부 데이터:
지급 기간 — 19행에서 확인 가능
총 지불 — 이 항목은 지불 목록 다음에 나타나고 "총 지불"이라는 제목이 없기 때문에 규칙을 찾기가 까다로웠습니다.
앞서 언급한 바와 같이 결제와 공제는 다를 수 있으며 매달 동일하지는 않습니다. 따라서 총 급여는 달마다 다른 행에 나타날 수 있습니다.
직원 이름 바로 뒤에 표시되는 것을 확인하고 이를 사용했습니다. 먼저 하드 코딩하여 추가한 후 나중에 외부에서 가져옵니다.
Nett Pay: 이 방법은 쉽습니다. 17행에 나와 있습니다.
테이블에 없는 값을 함수로 모았습니다.
결제 및 공제 세부정보: 이 부분이 정말 흥미로웠어요! for 루프에서 몇 밀리초를 절약하기 위해 행 배열을 자르는 것부터 시작하겠습니다. 그런 다음 목록 항목
과 다른 행을 구별해야 했습니다.
전체 파일 내에서 목록 항목만 이 규칙과 일치하는 것으로 확인되었습니다. 알파벳 문자로 시작하고 숫자로 끝나야 합니다 및에는 공백이 포함되어 있습니다(마지막 조건은 my
에서 잘못된 행을 필터링하는 것입니다). 급여명세서는 필요하지 않을 수도 있습니다).
예를 들어 연금 항목을 살펴보겠습니다.
main.py: # translate 1 pdf to 1 dict # loop over the pdf dir # save all dicts to 1 json file # translate json report to csv report
잔액(오른쪽 숫자)은 신경 쓰지 않지만 코드는 중요합니다(G는 총 급여에서 공제됨을 의미 - 세전) — 그리고 N은 세금 후 Nett 급여에서 공제됨을 의미합니다. 따라서 이상적으로는 json_obj["Pension (G)"]=150.00이 됩니다.
공백을 사용하여 선을 분할하겠습니다. 중복된 공백이 있으면 좋습니다. 이렇게 하면 두 단어 사이의 공백 분할과 두 필드 사이의 공백 분할을 구별할 수 있습니다.
설명:
첫 번째 이중 공백을 찾아 이를 통해 분할하겠습니다.
코드:
설명의 길이에 따라 공백의 양이 달라지므로 몇 개나 있는지 미리 알 수 없으므로 lstrip()도 사용하겠습니다. 이제 줄의 나머지 부분은 공백이 아닌 문자로 시작됩니다.
모든 목록 항목에 코드가 있는 것은 아니므로 줄이 코드로 시작하는지 아니면 숫자로 시작하는지 확인하고 싶습니다. 코드인 경우 — ()(여는 괄호 앞의 공백 포함)로 묶고 설명 문자열에 첨부합니다. 그렇지 않다면 아무것도 추가하지 마세요.
금액:
코드가 있다면 제거할 공간이 더 많아질 것입니다. 그렇지 않은 경우 라인에 두 가지 금액, 즉 월별 금액과 잔액
이 포함될 수 있습니다.제가 확인한 4가지 사례는 다음과 같습니다.
/payslips_pdf pdf_rows.txt report.json report.csv
카테고리와 코드를 추출한 후 다음이 남습니다.
PENSION G 150.00 587.49
2~3번 사례를 다루기 위해 양을 구분하는 공백의 색인을 찾아 꼬리를 잘라냅니다. 공백이 없는(일명 꼬리 없음) 첫 번째 경우에도 작동합니다.
사례 4를 다루기 위해 행에 단일 금액이 있는 두 가지 유형의 범주 간의 차이에 의존합니다. 첫 번째 유형은 급여와 유사하며 금액을 저장하려는 경우이고 두 번째 유형은 다음과 같습니다. 세금 원천징수 – 우리는 이를 무시하고 싶습니다. 차이점은 공제만이 표의 연간 잔액을 추적한다는 것입니다. 그래서 저는 -를 확인하고 있습니다.
모두 합하면 다음과 같습니다.
이것은 필수 단계가 아닙니다. 값을 내보내지 않고도 JSON 개체로 작업할 수 있습니다. 적어도 코딩 단계에서는 어떻게 보이는지 보는 것이 더 좋습니다.
여러 PDF 파일로 확장
원래는 파일 이름을 바꿔야 한다고 생각했는데(Payslip1.pdf -> Payslip01.pdf) 더 나은 해결 방법이 있습니다.
지불 및 공제 항목은 급여명세서마다 다를 수 있으므로 이 섹션은 단순한 번역 이상의 의미를 갖습니다. CSV는 관계형 데이터 세트입니다. 즉, 지불 및 공제의 모든 범주를 미리 알아야 하고, 급여 명세서가 존재하지 않는 경우 해당 항목을 비워 두어야 합니다. 반면에 JSON은 비관계형이며 각 항목은 해당 키를 지정합니다.
이를 염두에 두고 CSV 보고서의 첫 번째 단계는 카테고리를 수집하는 것입니다. 모든 카테고리.
카테고리 수집:
이제 언뜻 보면 Set을 사용하는 것이 좋겠다고 생각할 수도 있습니다. 왜냐하면 우리는 모든 카테고리가 한 번만 나타나기를 원하기 때문입니다. 나는 그것을 시도했다. 문제는 세트가 목록에 없다는 점이며, 원래 급여명세서에 나타나는 항목의 순서를 일치시키는 것이 중요하다고 생각합니다. 목록을 사용할 때 항목을 추가하기 전에 목록에 항목이 있는지 확인하는 것을 잊지 마세요.
필요
는 않지만 급여명세서 보고서에는 모든 지급액이 오른쪽에, 모든 공제액이 왼쪽에 혼합되지 않고 표시될 것으로 예상됩니다.
마지막으로, 지불금과 공제액을 분리하는 것은 아무 소용이 없기 때문에 단일 목록을 반환합니다. 분할은 지불금이 오른쪽에 표시되고 공제액이 왼쪽에 표시되도록 하기 위한 것이었습니다.
CSV 테이블 채우기:
이제 카테고리가 있으므로 CSV 테이블을 채울 수 있습니다.
VS 확장 RainbowCSV(또는 다른 IDE와 유사한 버전)를 다운로드하면 더 쉽게 읽을 수 있습니다
일단 제대로 작동한다는 것을 알게 되면 JSON 파일에 쓰거나 읽을 필요가 없습니다. JSON 개체를 직접 사용할 수 있습니다.
json_object를 사용하는 대신(json_object = json.dumps(json_payslips)에서와 같이) – json_payslips를 직접 사용합니다.
쓰기: report.json에 쓸 필요가 없습니다. 이 섹션을 제거할 수 있습니다.
읽기: json_payslips를 json_to_csv() 함수에 직접 전달하세요.
대본이 준비되면 동료 및 친구들과 공유하고 싶을 것입니다! 좋은 사용자 경험을 위해 직원에게 코드를 열도록 요청하는 대신 명령줄에서 직원 이름을 내보내도록 하겠습니다.
인수 읽기
사용자가 직원 이름을 입력했다고 가정하고 행복한 경로부터 시작하고 이를 사용하는 코드를 추가하겠습니다.
pdf_to_dict()에서는 EMPLOYEE_NAME = "IFAT NEEUMANN"을 하드 코딩하는 대신 직원 이름 = sys.argv[1] 인수에서 읽습니다. sys를 가져오는 것을 잊지 마세요!
이제 다른 시나리오를 생각해 보겠습니다.
직원 이름이 지정되지 않았습니다
사용자가 직원 이름을 입력하지 않으면 어떻게 되나요? 가능한 한 빨리 이를 확인하고 알리고 싶습니다!
따라서 메인 함수의 첫 번째 줄에 체크를 추가하겠습니다. 이제 직관은 거기에서 Employee_name 변수를 초기화하는 것입니다. 하지만 이렇게 하면 이 변수를 사용하는 함수에 도달할 때까지 함수 속성 버블링이 발생하게 되며 매우 깔끔한 접근 방식이라고 생각하지 않습니다.
마지막으로 이 필드에 액세스해 보고 거기에 없으면 확인하겠습니다.
main.py: # translate 1 pdf to 1 dict # loop over the pdf dir # save all dicts to 1 json file # translate json report to csv report
예외를 추가한다는 것은 print_warning() 함수가 main.py로 이동한다는 것을 의미합니다. 그렇지 않으면 오류가 발생합니다.
따옴표 없는 직원 이름
인용 요구 사항을 건너뛰고 인수를 반복하여 사용자 이름의 모든 부분을 수집할 수 있지만 이 접근 방식은 불필요하게 복잡해집니다.
급여명세서에 직원 이름이 나오지 않아요
급여 명세서에 기재된 직원의 이름이 없으면 총 급여를 확인할 수 없습니다.
마지막으로 main 함수에서 오류를 다시 잡아냅니다.
급여 명세서를 가지고 놀 때 사용할 수 있는 전체 코드는 다음과 같습니다.
https://cupofcode.blog/ |
위 내용은 주말 코딩: PDF 급여명세서를 단일 CSV 보고서로 전환의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!