{"id":15139,"date":"2025-06-01T16:00:33","date_gmt":"2025-06-01T07:00:33","guid":{"rendered":"https:\/\/www.sambuichi.jp\/?p=15139"},"modified":"2025-06-02T08:14:21","modified_gmt":"2025-06-01T23:14:21","slug":"python%e3%81%a7%e6%a7%8b%e9%80%a0%e5%8c%96%e3%82%a4%e3%83%b3%e3%83%9c%e3%82%a4%e3%82%b9csv%e3%82%92%e8%87%aa%e5%8b%95%e7%94%9f%e6%88%90%e3%81%99%e3%82%8b%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88","status":"publish","type":"post","link":"https:\/\/www.sambuichi.jp\/?p=15139","title":{"rendered":"Python\u3067\u69cb\u9020\u5316CSV\u3092\u81ea\u52d5\u751f\u6210\u3059\u308b\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u89e3\u8aac"},"content":{"rendered":"<p>Views: 35<\/p><div id=\"header\">\n<h1>Python\u3067\u69cb\u9020\u5316CSV\u3092\u81ea\u52d5\u751f\u6210\u3059\u308b\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u89e3\u8aac<\/h1>\n<div class=\"details\">\n<span id=\"author\" class=\"author\">ChatGPT (\u7de8\u96c6 \u4e09\u5206\u4e00\u4fe1\u4e4b\uff09<\/span><br \/>\n<span id=\"revdate\">2025-06-02<\/span>\n<\/div>\n<\/div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"quoteblock abstract\">\n<blockquote><p>\n\u672c\u8a18\u4e8b\u3067\u306f\u3001\u8907\u6570\u306eCSV\u30d5\u30a1\u30a4\u30eb\uff08\u8acb\u6c42\u66f8\u30fb\u8cb7\u624b\u30fb\u58f2\u624b\u30fb\u660e\u7d30\u30fb\u7a0e\u60c5\u5831\u306a\u3069\uff09\u3092\u3082\u3068\u306b\u3001\u69cb\u9020\u5316\u3055\u308c\u305f1\u679a\u307e\u305f\u306f\u8907\u6570\u306e\u8acb\u6c42\u66f8\u60c5\u5831\u3092\u51fa\u529b\u3059\u308bPython\u30b9\u30af\u30ea\u30d7\u30c8\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<br \/>\n\u4e2d\u5c0f\u4f01\u696d\u5171\u901aEDI\u3084XBRL-GL\u306a\u3069\u306e\u4ed5\u8a33\u5e33\u30fb\u30a4\u30f3\u30dc\u30a4\u30b9\u51e6\u7406\u306b\u5fdc\u7528\u53ef\u80fd\u3067\u3059\u3002\n<\/p><\/blockquote>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u80cc\u666f\">1. \u80cc\u666f<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>\u96fb\u5b50\u30a4\u30f3\u30dc\u30a4\u30b9\u3084\u69cb\u9020\u5316\u4f1a\u8a08\u30c7\u30fc\u30bf\u306e\u666e\u53ca\u306b\u3088\u308a\u3001\u8acb\u6c42\u30c7\u30fc\u30bf\u3092CSV\u5f62\u5f0f\u3067\u6a19\u6e96\u5316\u3057\u3001\u7a0e\u52d9\u30fb\u4f1a\u8a08\u30bd\u30d5\u30c8\u9593\u3067\u9023\u643a\u53ef\u80fd\u306b\u3059\u308b\u3053\u3068\u304c\u6c42\u3081\u3089\u308c\u3066\u3044\u307e\u3059\u3002\u672c\u30b9\u30af\u30ea\u30d7\u30c8\u306f\u3001\u305d\u306e\u305f\u3081\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u76ee\u7684\">2. \u30b9\u30af\u30ea\u30d7\u30c8\u306e\u76ee\u7684<\/h2>\n<div class=\"sectionbody\">\n<div class=\"ulist\">\n<ul>\n<li>\n<p>\u8acb\u6c42\u66f8\u3054\u3068\u306b\u69cb\u9020\u5316\u3055\u308c\u305f\u884c\u5f62\u5f0f\uff08\u30d8\u30c3\u30c0\u884c\u3001\u7a0e\u60c5\u5831\u884c\u3001\u660e\u7d30\u884c\uff09\u3092\u51fa\u529b<\/p>\n<\/li>\n<li>\n<p>\u5358\u4e00\u307e\u305f\u306f\u8907\u6570\u306e\u8acb\u6c42\u66f8\u3092\u5bfe\u8c61\u306b\u3001\u67d4\u8edf\u306a\u51fa\u529b<\/p>\n<\/li>\n<li>\n<p>Python\uff0bPandas\u306b\u3088\u308b\u30b7\u30f3\u30d7\u30eb\u306a\u5b9f\u88c5<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u30d5\u30a1\u30a4\u30eb\u69cb\u6210\">3. \u30d5\u30a1\u30a4\u30eb\u69cb\u6210<\/h2>\n<div class=\"sectionbody\">\n<table class=\"tableblock frame-all grid-all stretch\">\n<colgroup>\n<col style=\"width: 33.3333%;\">\n<col style=\"width: 66.6667%;\">\n<\/colgroup>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u30d5\u30a1\u30a4\u30eb\u540d<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u5185\u5bb9<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Invoice.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u8acb\u6c42\u66f8\u30d8\u30c3\u30c0\u60c5\u5831<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Buyer.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u8cb7\u624b\uff08\u8acb\u6c42\u5148\uff09\u30de\u30b9\u30bf<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Seller.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u58f2\u624b\uff08\u4f9b\u7d66\u8005\uff09\u30de\u30b9\u30bf<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">InvoiceLine.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u660e\u7d30\u884c\u60c5\u5831<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Item.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u5546\u54c1\u30de\u30b9\u30bf\uff08\u54c1\u76ee\u540d\u3001\u7a0e\u7387\u306a\u3069\uff09<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">TaxBreakdown.csv<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">\u7a0e\u533a\u5206\u3054\u3068\u306e\u7a0e\u60c5\u5831<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u51fa\u529b\u3055\u308c\u308bcsv\u69cb\u9020\">4. \u51fa\u529b\u3055\u308c\u308bCSV\u69cb\u9020<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>\u51fa\u529bCSV\u306f\u4ee5\u4e0b\u306e3\u968e\u5c64\u306e\u60c5\u5831\u3092\u542b\u307f\u307e\u3059\uff1a<\/p>\n<\/div>\n<div class=\"olist arabic\">\n<ol class=\"arabic\">\n<li>\n<p>\u8acb\u6c42\u66f8\u30d8\u30c3\u30c0\uff08dInvoice\uff09<\/p>\n<\/li>\n<li>\n<p>\u7a0e\u660e\u7d30\uff08dTaxBreakdown\uff09<\/p>\n<\/li>\n<li>\n<p>\u660e\u7d30\u884c\uff08dInvoiceLine\uff09<\/p>\n<\/li>\n<\/ol>\n<\/div>\n<div class=\"paragraph\">\n<p>\u3053\u308c\u306b\u3088\u308a\u3001\u30bf\u30d6\u5f62\u5f0f\u306e\u69cb\u9020\u5316CSV\uff08tidy data\uff09\u304c\u5b9f\u73fe\u3055\u308c\u307e\u3059\u3002<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u5b9f\u884c\u30b3\u30de\u30f3\u30c9\u4f8b\">5. \u5b9f\u884c\u30b3\u30de\u30f3\u30c9\u4f8b<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>\u5358\u4e00\u8acb\u6c42\u66f8\uff08\u4f8b\uff1a<code>INV002<\/code>\uff09\u3092\u51fa\u529b\uff1a<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-sh\" data-lang=\"sh\">python structured_invoice_csv.py --base_dir 2025\/202506\/20250601\/ \\\r\n       --invoice_id INV002 \\\r\n       --single_csv_path 2025\/202506\/20250601\/invoice_INV002.csv<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>\u5168\u8acb\u6c42\u66f8\u3092\u51fa\u529b\uff1a<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-sh\" data-lang=\"sh\">python structured_invoice_csv.py --base_dir 2025\/202506\/20250601\/ \\\r\n       --all_csv_path 2025\/202506\/20250601\/invoice_all.csv<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u4e3b\u306a\u51e6\u7406\u306e\u6d41\u308c\">6. \u4e3b\u306a\u51e6\u7406\u306e\u6d41\u308c<\/h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_1_\u5404csv\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\">6.1. 1. \u5404CSV\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f<\/h3>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-python\" data-lang=\"python\">invoice_df = pd.read_csv(...Invoice.csv)\r\nbuyer_df = pd.read_csv(...Buyer.csv)\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_2_\u30ab\u30e9\u30e0\u69cb\u9020\u5b9a\u7fa9\">6.2. 2. \u30ab\u30e9\u30e0\u69cb\u9020\u5b9a\u7fa9<\/h3>\n<div class=\"paragraph\">\n<p>\u51fa\u529bCSV\u306e\u5217\u69cb\u9020\u3092\u56fa\u5b9a\u3057\u3001\u8907\u6570\u30a4\u30f3\u30dc\u30a4\u30b9\u306b\u3082\u5bfe\u5fdc\u3002<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-python\" data-lang=\"python\">columns = [\r\n    \"dInvoice\", \"dTaxBreakdown\", \"dInvoiceLine\", ...\r\n]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_3_\u5358\u4e00\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529bexport_single_invoice\">6.3. 3. \u5358\u4e00\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529b\uff08<code>export_single_invoice<\/code>\uff09<\/h3>\n<div class=\"olist arabic\">\n<ol class=\"arabic\">\n<li>\n<p>\u30d8\u30c3\u30c0\u60c5\u5831\u306e\u62bd\u51fa\u3068\u51fa\u529b<\/p>\n<\/li>\n<li>\n<p>\u7a0e\u533a\u5206\u3054\u3068\u306b\u30e6\u30cb\u30fc\u30af\u30ad\u30fc\u3067\u4e26\u3079\u66ff\u3048\u3001<code>dTaxBreakdown<\/code> \u756a\u53f7\u3092\u4ed8\u4e0e<\/p>\n<\/li>\n<li>\n<p>\u660e\u7d30\u884c\u3092 <code>ID.factorize()<\/code> \u3067\u9806\u756a\u306b\u756a\u53f7\u4ed8\u3051\u3057\u51fa\u529b<\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_4_\u5168\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529bexport_all_invoices\">6.4. 4. \u5168\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529b\uff08<code>export_all_invoices<\/code>\uff09<\/h3>\n<div class=\"olist arabic\">\n<ol class=\"arabic\">\n<li>\n<p>\u8acb\u6c42\u66f8\u3092ID\u9806\u306b\u30bd\u30fc\u30c8\u3057 <code>dInvoice<\/code> \u3092\u9023\u756a\u4ed8\u4e0e<\/p>\n<\/li>\n<li>\n<p>\u7a0e\u3068\u660e\u7d30\u306f\u5404\u30a4\u30f3\u30dc\u30a4\u30b9\u3054\u3068\u306b\u7e70\u308a\u8fd4\u3057\u51fa\u529b<\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_5_\u66f8\u304d\u51fa\u3057\u51e6\u7406\">6.5. 5. \u66f8\u304d\u51fa\u3057\u51e6\u7406<\/h3>\n<div class=\"paragraph\">\n<p>NA\/\u7a7a\u767d\u3092\u9069\u5207\u306b\u51e6\u7406\u3057\u3001<code>utf-8-sig<\/code> \u3067CSV\u4fdd\u5b58\u3002<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-python\" data-lang=\"python\">df.to_csv(path, index=False, encoding=\"utf-8-sig\")<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_launch_json\u4f8bvs_code\">7. launch.json\u4f8b\uff08VS Code\uff09<\/h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-json\" data-lang=\"json\">{\r\n  \"name\": \"\u69cb\u9020\u5316\u30a4\u30f3\u30dc\u30a4\u30b9CSV\u51fa\u529b\",\r\n  \"type\": \"python\",\r\n  \"request\": \"launch\",\r\n  \"program\": \"${workspaceFolder}\/structured_invoice_csv.py\",\r\n  \"args\": [\r\n    \"--base_dir\", \"2025\/202506\/20250601\/\",\r\n    \"--invoice_id\", \"INV002\",\r\n    \"--single_csv_path\", \"2025\/202506\/20250601\/invoice_INV002.csv\",\r\n    \"--all_csv_path\", \"2025\/202506\/20250601\/invoice_all.csv\"\r\n  ]\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_\u304a\u308f\u308a\u306b\">8. \u304a\u308f\u308a\u306b<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>\u3053\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u306f\u3001\u5b9f\u52d9\u3067\u306e\u8acb\u6c42\u66f8\u3084\u30a4\u30f3\u30dc\u30a4\u30b9\u306e\u69cb\u9020\u5316\u51e6\u7406\u306b\u305d\u306e\u307e\u307e\u6d3b\u7528\u3067\u304d\u307e\u3059\u3002<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content scroll-pre\">\n<pre class=\"highlight\"><code class=\"language-python\" data-lang=\"python\">#!\/usr\/bin\/env python3\r\n# coding: utf-8\r\n\"\"\"\r\nUniversal Audit Data Adaptor: structured_csv.py\r\n\r\nThis script processes CSV files dumped from the RDB and converts them into a hierarchically organized structured CSV format.\r\n\r\ndesigned by SAMBUICHI, Nobuyuki (Sambuichi Professional Engineers Office)\r\nwritten by SAMBUICHI, Nobuyuki (Sambuichi Professional Engineers Office)\r\n\r\nCreation Date: 2025-05-30\r\nLast Modified: 2025-06-02\r\n\r\nMIT License\r\n\r\n(c) 2024 SAMBUICHI Nobuyuki (Sambuichi Professional Engineers Office)\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\r\n\"\"\"\r\nimport pandas as pd\r\nimport os\r\nimport argparse\r\n\r\ndef main(base_dir, invoice_id=None, single_csv_path=None, all_csv_path=None):\r\n    # \u51fa\u529b\u30d5\u30a1\u30a4\u30eb\u540d\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\uff08\u6307\u5b9a\u304c\u306a\u3051\u308c\u3070\u6a19\u6e96\u306e\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u4f7f\u7528\uff09\r\n    if single_csv_path is None:\r\n        single_csv_path = os.path.join(base_dir, \"structured_invoice_export0.csv\")\r\n    if all_csv_path is None:\r\n        all_csv_path = os.path.join(base_dir, \"structured_invoice_export1.csv\")\r\n\r\n    # --- CSV \u8aad\u307f\u8fbc\u307f ---\r\n    # \u5404\u7a2e\u30de\u30b9\u30bf\u30d5\u30a1\u30a4\u30eb\u3068\u53d6\u5f15\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3080\r\n    invoice_df = pd.read_csv(os.path.join(base_dir, \"Invoice.csv\"), dtype=str)\r\n    buyer_df = pd.read_csv(os.path.join(base_dir, \"Buyer.csv\"), dtype=str)\r\n    seller_df = pd.read_csv(os.path.join(base_dir, \"Seller.csv\"), dtype=str)\r\n    tax_df = pd.read_csv(os.path.join(base_dir, \"TaxBreakdown.csv\"), dtype=str)\r\n    line_df = pd.read_csv(os.path.join(base_dir, \"InvoiceLine.csv\"), dtype=str)\r\n    item_df = pd.read_csv(os.path.join(base_dir, \"Item.csv\"), dtype=str)\r\n\r\n    # --- \u30ab\u30e9\u30e0\u5b9a\u7fa9 ---\r\n    # \u51fa\u529bCSV\u306e\u5217\u9806\u3068\u69cb\u9020\u3092\u5b9a\u7fa9\u3059\u308b\r\n    columns = [\r\n        \"dInvoice\", \"dTaxBreakdown\", \"dInvoiceLine\",\r\n        \"Invoice.ID\", \"issueDate\", \"typeCode\", \"dueDate\",\r\n        \"Buyer.name\", \"Seller.name\", \"Seller.taxID\",\r\n        \"sumOfLineNetAmount\", \"totalAmountWithoutTax\", \"totalTaxAmount\", \"totalAmountWithTax\",\r\n        \"TaxBreakdown.taxCategoryCode\", \"TaxBreakdown.taxCategoryRate\", \"TaxBreakdown.taxCategoryTaxAmount\",\r\n        \"InvoiceLine.ID\", \"InvoiceLine.netAmount\", \"InvoiceLine.quantity\", \"InvoiceLine.uom\",\r\n        \"Item.ID\", \"Item.name\", \"Item.price\", \"Item.baseQuantity\", \"Item.uom\",\r\n        \"Item.taxCategoryCode\", \"Item.taxCategoryRate\"\r\n    ]\r\n\r\n    # --- \u5358\u4e00\u8acb\u6c42\u66f8\u306e\u51fa\u529b\u51e6\u7406 ---\r\n    def export_single_invoice(inv_id):\r\n        rows = []\r\n        # \u5bfe\u8c61\u306e\u8acb\u6c42\u66f8\u30ec\u30b3\u30fc\u30c9\u3092\u62bd\u51fa\r\n        i = invoice_df[invoice_df[\"ID\"] == inv_id]\r\n        if i.empty:\r\n            raise ValueError(f\"Invoice {inv_id} not found.\")\r\n        i = i.iloc[0]\r\n        # Buyer\u304a\u3088\u3073Seller\u60c5\u5831\u3092\u53d6\u5f97\r\n        b = buyer_df[buyer_df[\"ID\"] == i[\"buyerID\"]].iloc[0]\r\n        s = seller_df[seller_df[\"ID\"] == i[\"sellerID\"]].iloc[0]\r\n\r\n        # \u8acb\u6c42\u66f8\u30d8\u30c3\u30c0\u884c\u3092\u8ffd\u52a0\r\n        rows.append({\r\n            \"dInvoice\": 1, \"dTaxBreakdown\": pd.NA, \"dInvoiceLine\": pd.NA,\r\n            \"Invoice.ID\": i[\"ID\"], \"issueDate\": i.get(\"issueDate\", \"\"), \"typeCode\": i.get(\"typeCode\", \"\"),\r\n            \"dueDate\": i.get(\"dueDate\", \"\"), \"Buyer.name\": b.get(\"name\", \"\"), \"Seller.name\": s.get(\"name\", \"\"),\r\n            \"Seller.taxID\": s.get(\"taxID\", \"\"), \"sumOfLineNetAmount\": i.get(\"sumOfLineNetAmount\", \"\"),\r\n            \"totalAmountWithoutTax\": i.get(\"totalAmountWithoutTax\", \"\"), \"totalTaxAmount\": i.get(\"totalTaxAmount\", \"\"),\r\n            \"totalAmountWithTax\": i.get(\"totalAmountWithTax\", \"\"),\r\n            **{k: \"\" for k in columns[14:]}\r\n        })\r\n\r\n        # \u7a0e\u60c5\u5831\u306e\u51fa\u529b\uff08\u30e6\u30cb\u30fc\u30af\u306a\u30ab\u30c6\u30b4\u30ea\u3054\u3068\u306b\u4e26\u3079\u66ff\u3048\u3066\u9806\u756a\u3092\u632f\u308b\uff09\r\n        tb = tax_df[tax_df[\"invoiceID\"] == inv_id].copy()\r\n        tb[\"key\"] = tb[\"taxCategoryCode\"].fillna('') + \"|\" + tb[\"taxCategoryRate\"].fillna('')\r\n        tb[\"dTaxBreakdown\"] = tb[\"key\"].factorize()[0] + 1\r\n\r\n        for _, t in tb.iterrows():\r\n            row = {k: \"\" for k in columns}\r\n            row.update({\r\n                \"dInvoice\": 1,\r\n                \"dTaxBreakdown\": t[\"dTaxBreakdown\"],\r\n                \"TaxBreakdown.taxCategoryCode\": t.get(\"taxCategoryCode\", \"\"),\r\n                \"TaxBreakdown.taxCategoryRate\": t.get(\"taxCategoryRate\", \"\"),\r\n                \"TaxBreakdown.taxCategoryTaxAmount\": t.get(\"taxCategoryTaxAmount\", \"\")\r\n            })\r\n            rows.append(row)\r\n\r\n        # \u660e\u7d30\u884c\u60c5\u5831\u306e\u51fa\u529b\r\n        il = line_df[line_df[\"invoiceID\"] == inv_id].copy()\r\n        il[\"dInvoiceLine\"] = il[\"ID\"].factorize()[0] + 1\r\n\r\n        for _, l in il.iterrows():\r\n            item = item_df[item_df[\"ID\"] == l[\"itemID\"]].iloc[0]\r\n            row = {k: \"\" for k in columns}\r\n            row.update({\r\n                \"dInvoice\": 1,\r\n                \"dInvoiceLine\": l[\"dInvoiceLine\"],\r\n                \"InvoiceLine.ID\": l.get(\"ID\", \"\"),\r\n                \"InvoiceLine.netAmount\": l.get(\"netAmount\", \"\"),\r\n                \"InvoiceLine.quantity\": l.get(\"quantity\", \"\"),\r\n                \"InvoiceLine.uom\": l.get(\"uom\", \"\"),\r\n                \"Item.ID\": item.get(\"ID\", \"\"), \"Item.name\": item.get(\"name\", \"\"),\r\n                \"Item.price\": item.get(\"price\", \"\"), \"Item.baseQuantity\": item.get(\"baseQuantity\", \"\"),\r\n                \"Item.uom\": item.get(\"uom\", \"\"), \"Item.taxCategoryCode\": item.get(\"taxCategoryCode\", \"\"),\r\n                \"Item.taxCategoryRate\": item.get(\"taxCategoryRate\", \"\")\r\n            })\r\n            rows.append(row)\r\n\r\n        return pd.DataFrame(rows, columns=columns)\r\n\r\n    # --- \u5168\u8acb\u6c42\u66f8\u306e\u51fa\u529b\u51e6\u7406 ---\r\n    def export_all_invoices():\r\n        rows = []\r\n        invoice_df_sorted = invoice_df.sort_values(\"ID\").copy()\r\n        invoice_df_sorted[\"dInvoice\"] = range(1, len(invoice_df_sorted) + 1)\r\n\r\n        for _, i in invoice_df_sorted.iterrows():\r\n            d_inv = i[\"dInvoice\"]\r\n            b = buyer_df[buyer_df[\"ID\"] == i[\"buyerID\"]].iloc[0]\r\n            s = seller_df[seller_df[\"ID\"] == i[\"sellerID\"]].iloc[0]\r\n\r\n            # \u8acb\u6c42\u66f8\u30d8\u30c3\u30c0\u884c\r\n            rows.append({\r\n                \"dInvoice\": d_inv, \"dTaxBreakdown\": pd.NA, \"dInvoiceLine\": pd.NA,\r\n                \"Invoice.ID\": i[\"ID\"], \"issueDate\": i.get(\"issueDate\", \"\"), \"typeCode\": i.get(\"typeCode\", \"\"),\r\n                \"dueDate\": i.get(\"dueDate\", \"\"), \"Buyer.name\": b.get(\"name\", \"\"), \"Seller.name\": s.get(\"name\", \"\"),\r\n                \"Seller.taxID\": s.get(\"taxID\", \"\"), \"sumOfLineNetAmount\": i.get(\"sumOfLineNetAmount\", \"\"),\r\n                \"totalAmountWithoutTax\": i.get(\"totalAmountWithoutTax\", \"\"), \"totalTaxAmount\": i.get(\"totalTaxAmount\", \"\"),\r\n                \"totalAmountWithTax\": i.get(\"totalAmountWithTax\", \"\"),\r\n                **{k: \"\" for k in columns[14:]}\r\n            })\r\n\r\n            # \u7a0e\u30d6\u30ec\u30fc\u30af\u30c0\u30a6\u30f3\u884c\r\n            tb = tax_df[tax_df[\"invoiceID\"] == i[\"ID\"]].copy()\r\n            tb[\"key\"] = tb[\"taxCategoryCode\"].fillna('') + \"|\" + tb[\"taxCategoryRate\"].fillna('')\r\n            tb[\"dTaxBreakdown\"] = tb[\"key\"].factorize()[0] + 1\r\n\r\n            for _, t in tb.iterrows():\r\n                row = {k: \"\" for k in columns}\r\n                row.update({\r\n                    \"dInvoice\": d_inv,\r\n                    \"dTaxBreakdown\": t[\"dTaxBreakdown\"],\r\n                    \"TaxBreakdown.taxCategoryCode\": t.get(\"taxCategoryCode\", \"\"),\r\n                    \"TaxBreakdown.taxCategoryRate\": t.get(\"taxCategoryRate\", \"\"),\r\n                    \"TaxBreakdown.taxCategoryTaxAmount\": t.get(\"taxCategoryTaxAmount\", \"\")\r\n                })\r\n                rows.append(row)\r\n\r\n            # \u660e\u7d30\u884c\r\n            il = line_df[line_df[\"invoiceID\"] == i[\"ID\"]].copy()\r\n            il[\"dInvoiceLine\"] = il[\"ID\"].factorize()[0] + 1\r\n\r\n            for _, l in il.iterrows():\r\n                item = item_df[item_df[\"ID\"] == l[\"itemID\"]].iloc[0]\r\n                row = {k: \"\" for k in columns}\r\n                row.update({\r\n                    \"dInvoice\": d_inv,\r\n                    \"dInvoiceLine\": l[\"dInvoiceLine\"],\r\n                    \"InvoiceLine.ID\": l.get(\"ID\", \"\"),\r\n                    \"InvoiceLine.netAmount\": l.get(\"netAmount\", \"\"),\r\n                    \"InvoiceLine.quantity\": l.get(\"quantity\", \"\"),\r\n                    \"InvoiceLine.uom\": l.get(\"uom\", \"\"),\r\n                    \"Item.ID\": item.get(\"ID\", \"\"), \"Item.name\": item.get(\"name\", \"\"),\r\n                    \"Item.price\": item.get(\"price\", \"\"), \"Item.baseQuantity\": item.get(\"baseQuantity\", \"\"),\r\n                    \"Item.uom\": item.get(\"uom\", \"\"), \"Item.taxCategoryCode\": item.get(\"taxCategoryCode\", \"\"),\r\n                    \"Item.taxCategoryRate\": item.get(\"taxCategoryRate\", \"\")\r\n                })\r\n                rows.append(row)\r\n\r\n        return pd.DataFrame(rows, columns=columns)\r\n\r\n    # --- \u51e6\u7406\u5206\u5c90 ---\r\n    if invoice_id:\r\n        # \u5358\u4e00\u8acb\u6c42\u66f8\u51fa\u529b\r\n        if single_csv_path:\r\n            df0 = export_single_invoice(invoice_id)\r\n            for col in [\"dInvoice\", \"dTaxBreakdown\", \"dInvoiceLine\"]:\r\n                df0[col] = df0[col].apply(lambda x: pd.NA if not str(x).strip().isdigit() else int(x)).astype(\"Int64\")\r\n            df0.to_csv(single_csv_path, index=False, encoding=\"utf-8-sig\")\r\n            print(f\"\u2705 Exported: {single_csv_path}\")\r\n        # \u5168\u8acb\u6c42\u66f8\u3082\u51fa\u529b\r\n        if all_csv_path:\r\n            df1 = export_all_invoices()\r\n            for col in [\"dInvoice\", \"dTaxBreakdown\", \"dInvoiceLine\"]:\r\n                df1[col] = df1[col].apply(lambda x: pd.NA if not str(x).strip().isdigit() else int(x)).astype(\"Int64\")\r\n            df1.to_csv(all_csv_path, index=False, encoding=\"utf-8-sig\")\r\n            print(f\"\u2705 Exported: {all_csv_path}\")\r\n    else:\r\n        # \u5168\u8acb\u6c42\u66f8\u51fa\u529b\uff08\u5358\u4f53\u8acb\u6c42\u66f8ID\u672a\u6307\u5b9a\u6642\uff09\r\n        df1 = export_all_invoices()\r\n        for col in [\"dInvoice\", \"dTaxBreakdown\", \"dInvoiceLine\"]:\r\n            df1[col] = df1[col].apply(lambda x: pd.NA if not str(x).strip().isdigit() else int(x)).astype(\"Int64\")\r\n        df1.to_csv(all_csv_path, index=False, encoding=\"utf-8-sig\")\r\n        print(f\"\u2705 Exported: {all_csv_path}\")\r\n\r\nif __name__ == \"__main__\":\r\n    parser = argparse.ArgumentParser(description=\"\u69cb\u9020\u5316\u30a4\u30f3\u30dc\u30a4\u30b9CSV\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\")\r\n    parser.add_argument(\"--base_dir\", required=True, help=\"CSV\u30d5\u30a1\u30a4\u30eb\u683c\u7d0d\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\")\r\n    parser.add_argument(\"--invoice_id\", help=\"\u5358\u4e00\u8acb\u6c42\u66f8ID\uff08\u6307\u5b9a\u6642\u306f\u305d\u306e\u8acb\u6c42\u66f8\u3092\u51fa\u529b\uff09\")\r\n    parser.add_argument(\"--single_csv_path\", help=\"\u5358\u4e00\u8acb\u6c42\u66f8\u306e\u51fa\u529b\u5148\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\")\r\n    parser.add_argument(\"--all_csv_path\", help=\"\u5168\u8acb\u6c42\u66f8\u306e\u51fa\u529b\u5148\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\")\r\n    args = parser.parse_args()\r\n    main(\r\n        args.base_dir,\r\n        invoice_id=args.invoice_id,\r\n        single_csv_path=args.single_csv_path,\r\n        all_csv_path=args.all_csv_path\r\n    )<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2025-06-02 07:51:01 +0900\n<\/div>\n<\/div>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">\u76ee\u6b21<\/div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_\u80cc\u666f\">1. \u80cc\u666f<\/a><\/li>\n<li><a href=\"#_\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u76ee\u7684\">2. \u30b9\u30af\u30ea\u30d7\u30c8\u306e\u76ee\u7684<\/a><\/li>\n<li><a href=\"#_\u30d5\u30a1\u30a4\u30eb\u69cb\u6210\">3. \u30d5\u30a1\u30a4\u30eb\u69cb\u6210<\/a><\/li>\n<li><a href=\"#_\u51fa\u529b\u3055\u308c\u308bcsv\u69cb\u9020\">4. \u51fa\u529b\u3055\u308c\u308bCSV\u69cb\u9020<\/a><\/li>\n<li><a href=\"#_\u5b9f\u884c\u30b3\u30de\u30f3\u30c9\u4f8b\">5. \u5b9f\u884c\u30b3\u30de\u30f3\u30c9\u4f8b<\/a><\/li>\n<li><a href=\"#_\u4e3b\u306a\u51e6\u7406\u306e\u6d41\u308c\">6. \u4e3b\u306a\u51e6\u7406\u306e\u6d41\u308c<\/a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_1_\u5404csv\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\">6.1. 1. \u5404CSV\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f<\/a><\/li>\n<li><a href=\"#_2_\u30ab\u30e9\u30e0\u69cb\u9020\u5b9a\u7fa9\">6.2. 2. \u30ab\u30e9\u30e0\u69cb\u9020\u5b9a\u7fa9<\/a><\/li>\n<li><a href=\"#_3_\u5358\u4e00\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529bexport_single_invoice\">6.3. 3. \u5358\u4e00\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529b\uff08<code>export_single_invoice<\/code>\uff09<\/a><\/li>\n<li><a href=\"#_4_\u5168\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529bexport_all_invoices\">6.4. 4. \u5168\u30a4\u30f3\u30dc\u30a4\u30b9\u51fa\u529b\uff08<code>export_all_invoices<\/code>\uff09<\/a><\/li>\n<li><a href=\"#_5_\u66f8\u304d\u51fa\u3057\u51e6\u7406\">6.5. 5. \u66f8\u304d\u51fa\u3057\u51e6\u7406<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#_launch_json\u4f8bvs_code\">7. launch.json\u4f8b\uff08VS Code\uff09<\/a><\/li>\n<li><a href=\"#_\u304a\u308f\u308a\u306b\">8. \u304a\u308f\u308a\u306b<\/a><\/li>\n<\/ul>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Views: 35 Python\u3067\u69cb\u9020\u5316CSV\u3092\u81ea\u52d5\u751f\u6210\u3059\u308b\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u89e3\u8aac ChatGPT (\u7de8\u96c6 \u4e09\u5206\u4e00\u4fe1\u4e4b\uff09 2025-06-02 \u672c\u8a18\u4e8b\u3067\u306f\u3001\u8907\u6570\u306eCSV\u30d5\u30a1\u30a4\u30eb\uff08\u8acb\u6c42\u66f8\u30fb\u8cb7\u624b\u30fb\u58f2\u624b\u30fb\u660e\u7d30\u30fb\u7a0e\u60c5\u5831\u306a\u3069\uff09\u3092\u3082\u3068\u306b\u3001 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":14948,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[71,45,49,68,82],"tags":[],"_links":{"self":[{"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/posts\/15139"}],"collection":[{"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=15139"}],"version-history":[{"count":8,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/posts\/15139\/revisions"}],"predecessor-version":[{"id":15151,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/posts\/15139\/revisions\/15151"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=\/wp\/v2\/media\/14948"}],"wp:attachment":[{"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=15139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sambuichi.jp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=15139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}