シート取得機能を備えた強化されたGoogle Sheets統合
- id: get_full_sheet_data
name: get_full_sheet_data
tool: GOOGLE_SHEETS_GET_SHEET
config:
- name: credentials
value: "{{secrets.GOOGLE_SHEETS_CREDENTIALS}}"
input:
- name: sheet_id
value: "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
- name: sheet_name
value: "Sheet1" # オプション: デフォルトは最初のシート
- name: include_formatting
value: true
- name: include_metadata
value: true
- id: analyze_sheet_structure
name: analyze_sheet_structure
tool: PYTHON_SANDBOX_RUN
input:
- name: code
value: |
import json
# 取得したシートデータを分析
sheet_data = json.loads('''{{steps.get_full_sheet_data.result.sheet_data}}''')
print("Google Sheet分析")
print("=" * 20)
# 基本情報
print(f"シート名: {sheet_data.get('sheet_name', '不明')}")
print(f"シートID: {sheet_data.get('sheet_id', '不明')}")
# データ次元
rows = sheet_data.get('rows', [])
if rows:
max_cols = max(len(row) for row in rows)
print(f"サイズ: {len(rows)}行 × {max_cols}列")
# データプレビュー
print("\nデータプレビュー(最初の5行):")
for i, row in enumerate(rows[:5], 1):
print(f"行{i}: {row[:5]}...") # 最初の5列を表示
else:
print("シートにデータが見つかりません")
# メタデータ
if 'metadata' in sheet_data:
metadata = sheet_data['metadata']
print(f"\nメタデータ:")
print(f" 最終更新: {metadata.get('modified_time', '不明')}")
print(f" 所有者: {metadata.get('owner', '不明')}")
- id: convert_to_structured_format
name: convert_to_structured_format
tool: PYTHON_SANDBOX_RUN
input:
- name: code
value: |
import json
sheet_data = json.loads('''{{steps.get_full_sheet_data.result.sheet_data}}''')
rows = sheet_data.get('rows', [])
if not rows:
print("変換するデータがありません")
else:
# 最初の行にヘッダーがあると仮定
headers = rows[0] if rows else []
data_rows = rows[1:] if len(rows) > 1 else []
# オブジェクトの配列に変換
structured_data = []
for row in data_rows:
row_obj = {}
for i, header in enumerate(headers):
value = row[i] if i < len(row) else ""
row_obj[header] = value
structured_data.append(row_obj)
# 構造化データを出力
result = {
"headers": headers,
"data": structured_data,
"record_count": len(structured_data)
}
print(json.dumps(result, indent=2, ensure_ascii=False))
- id: export_structured_data
name: export_structured_data
tool: OUTPUT_FILE
input:
- name: content
value: "{{steps.convert_to_structured_format.result.stdout}}"
- name: filename
value: "google_sheets_export_{{date | format('YYYY-MM-DD')}}.json"
- name: fileType
value: "json"
- id: get_workbook_info
name: get_workbook_info
tool: GOOGLE_SHEETS_GET_SHEET
config:
- name: credentials
value: "{{secrets.GOOGLE_SHEETS_CREDENTIALS}}"
input:
- name: sheet_id
value: "{{input.workbook_id}}"
- name: get_sheet_list
value: true # ワークブック内のすべてのシートのリストを取得
- id: process_all_sheets
name: process_all_sheets
tool: PYTHON_SANDBOX_RUN
input:
- name: code
value: |
import json
# ワークブックからシートリストを取得
workbook_info = json.loads('''{{steps.get_workbook_info.result.workbook_info}}''')
sheets = workbook_info.get('sheets', [])
print("マルチシート処理計画")
print("=" * 25)
print(f"ワークブックID: {workbook_info.get('workbook_id', '不明')}")
print(f"総シート数: {len(sheets)}")
print("\n処理するシート:")
processing_plan = []
for i, sheet in enumerate(sheets):
sheet_name = sheet.get('name', f'Sheet{i+1}')
sheet_info = {
"sheet_name": sheet_name,
"step_id": f"get_sheet_{i+1}",
"processing_order": i+1
}
processing_plan.append(sheet_info)
print(f" {i+1}. {sheet_name}")
print(f"\n{len(processing_plan)}シートの処理計画を作成しました")
print(json.dumps(processing_plan, indent=2, ensure_ascii=False))
- id: get_sales_sheet
name: get_sales_sheet
tool: GOOGLE_SHEETS_GET_SHEET
config:
- name: credentials
value: "{{secrets.GOOGLE_SHEETS_CREDENTIALS}}"
input:
- name: sheet_id
value: "{{input.workbook_id}}"
- name: sheet_name
value: "Sales Data"
- name: include_formatting
value: true
- id: get_inventory_sheet
name: get_inventory_sheet
tool: GOOGLE_SHEETS_GET_SHEET
config:
- name: credentials
value: "{{secrets.GOOGLE_SHEETS_CREDENTIALS}}"
input:
- name: sheet_id
value: "{{input.workbook_id}}"
- name: sheet_name
value: "Inventory"
- name: include_formatting
value: true
- id: consolidate_workbook_data
name: consolidate_workbook_data
tool: PYTHON_SANDBOX_RUN
input:
- name: code
value: |
import json
from datetime import datetime
# 複数シートからデータを統合
sales_data = json.loads('''{{steps.get_sales_sheet.result.sheet_data}}''')
inventory_data = json.loads('''{{steps.get_inventory_sheet.result.sheet_data}}''')
consolidated_report = {
"report_date": datetime.now().isoformat(),
"workbook_id": "{{input.workbook_id}}",
"sheets_processed": [],
"summary_statistics": {},
"data_quality_checks": []
}
# 売上データを処理
if sales_data.get('rows'):
sales_rows = len(sales_data['rows']) - 1 # ヘッダーを除く
consolidated_report["sheets_processed"].append({
"sheet_name": "Sales Data",
"row_count": sales_rows,
"status": "processed"
})
# 在庫データを処理
if inventory_data.get('rows'):
inventory_rows = len(inventory_data['rows']) - 1 # ヘッダーを除く
consolidated_report["sheets_processed"].append({
"sheet_name": "Inventory",
"row_count": inventory_rows,
"status": "processed"
})
# サマリー統計を計算
total_rows = sum(sheet["row_count"] for sheet in consolidated_report["sheets_processed"])
consolidated_report["summary_statistics"] = {
"total_data_rows": total_rows,
"sheets_processed": len(consolidated_report["sheets_processed"]),
"processing_time": "{{date | format('HH:mm:ss')}}"
}
print("ワークブック統合完了")
print("=" * 20)
print(json.dumps(consolidated_report, indent=2, ensure_ascii=False))
- id: save_consolidated_report
name: save_consolidated_report
tool: OUTPUT_FILE
input:
- name: content
value: "{{steps.consolidate_workbook_data.result.stdout}}"
- name: filename
value: "workbook_consolidation_report.json"
- name: fileType
value: "json"
- id: retrieve_data_for_analysis
name: retrieve_data_for_analysis
tool: GOOGLE_SHEETS_GET_SHEET
config:
- name: credentials
value: "{{secrets.GOOGLE_SHEETS_CREDENTIALS}}"
input:
- name: sheet_id
value: "{{input.analysis_sheet_id}}"
- name: sheet_name
value: "{{input.sheet_name}}"
- name: include_formatting
value: true
- name: include_metadata
value: true
- id: perform_data_quality_analysis
name: perform_data_quality_analysis
tool: PYTHON_SANDBOX_RUN
input:
- name: code
value: |
import json
import re
from collections import Counter
# データ品質を分析
sheet_data = json.loads('''{{steps.retrieve_data_for_analysis.result.sheet_data}}''')
rows = sheet_data.get('rows', [])
if not rows:
print("分析するデータが見つかりません")
else:
headers = rows[0] if rows else []
data_rows = rows[1:] if len(rows) > 1 else []
print("データ品質分析レポート")
print("=" * 25)
print(f"データセット: {sheet_data.get('sheet_name', '不明')}")
print(f"総レコード数: {len(data_rows)}")
print(f"総列数: {len(headers)}")
print()
# 列ごとの分析
quality_report = {
"overall_stats": {
"total_records": len(data_rows),
"total_columns": len(headers),
"completeness_score": 0
},
"column_analysis": [],
"data_issues": []
}
total_cells = 0
empty_cells = 0
for col_idx, header in enumerate(headers):
col_values = [row[col_idx] if col_idx < len(row) else "" for row in data_rows]
# 列統計を計算
non_empty_values = [v for v in col_values if str(v).strip()]
empty_count = len(col_values) - len(non_empty_values)
completeness = (len(non_empty_values) / len(col_values)) * 100 if col_values else 0
# データ型検出
numeric_count = sum(1 for v in non_empty_values if str(v).replace('.', '').replace('-', '').isdigit())
date_count = sum(1 for v in non_empty_values if re.match(r'\d{1,2}[/-]\d{1,2}[/-]\d{2,4}', str(v)))
email_count = sum(1 for v in non_empty_values if '@' in str(v) and '.' in str(v))
likely_type = "テキスト"
if numeric_count / len(non_empty_values) > 0.8 if non_empty_values else False:
likely_type = "数値"
elif date_count / len(non_empty_values) > 0.5 if non_empty_values else False:
likely_type = "日付"
elif email_count / len(non_empty_values) > 0.5 if non_empty_values else False:
likely_type = "メール"
col_analysis = {
"column_name": header,
"completeness_percent": round(completeness, 2),
"empty_cells": empty_count,
"likely_data_type": likely_type,
"unique_values": len(set(non_empty_values)),
"sample_values": non_empty_values[:3]
}
quality_report["column_analysis"].append(col_analysis)
total_cells += len(col_values)
empty_cells += empty_count
# 潜在的な問題を特定
if completeness < 90:
quality_report["data_issues"].append(f"列'{header}'の完全性が低い({completeness:.1f}%)")
if len(set(non_empty_values)) == 1 and non_empty_values:
quality_report["data_issues"].append(f"列'{header}'には1つの一意の値しかない")
# 全体の完全性スコア
overall_completeness = ((total_cells - empty_cells) / total_cells) * 100 if total_cells > 0 else 0
quality_report["overall_stats"]["completeness_score"] = round(overall_completeness, 2)
print(f"全体データ完全性: {overall_completeness:.1f}%")
print()
# 列分析を表示
print("列分析:")
for col in quality_report["column_analysis"]:
print(f" 📊 {col['column_name']}")
print(f" 完全性: {col['completeness_percent']}%")
print(f" 型: {col['likely_data_type']}")
print(f" 一意の値: {col['unique_values']}")
print()
# 問題を表示
if quality_report["data_issues"]:
print("🚨 データ品質の問題:")
for issue in quality_report["data_issues"]:
print(f" - {issue}")
else:
print("✅ 主要なデータ品質の問題は検出されませんでした")
print("\n" + json.dumps(quality_report, indent=2, ensure_ascii=False))
- id: create_quality_recommendations
name: create_quality_recommendations
tool: OPENAI_INVOKE
config:
- name: version
value: gpt-4
input:
- name: prompt
value: |
このデータ品質分析レポートに基づいて、データ品質向上のための具体的な推奨事項を提供してください:
{{steps.perform_data_quality_analysis.result.stdout}}
以下を提供してください:
1. 最初に対処すべき優先度の高い問題
2. データ完全性を改善するための具体的なステップ
3. 実装すべきデータ検証ルール
4. 継続的なデータメンテナンスのベストプラクティス
5. 推奨されるデータクリーニングワークフロー
- id: save_quality_analysis_report
name: save_quality_analysis_report
tool: OUTPUT_FILE
input:
- name: content
value: |
Google Sheetsデータ品質分析レポート
==================================
生成日時: {{date | format('YYYY-MM-DD HH:mm:ss')}}
## 分析結果
{{steps.perform_data_quality_analysis.result.stdout}}
## 推奨事項
{{steps.create_quality_recommendations.result.content}}
## 次のステップ
1. 高優先度のデータ品質問題に対処
2. 推奨されるデータ検証ルールを実装
3. 定期的なデータ品質監視を設定
4. データ入力のベストプラクティスをユーザーに研修
5. 自動データクリーニングワークフローを検討
- name: filename
value: "data_quality_analysis_{{date | format('YYYY-MM-DD')}}.txt"
- name: fileType
value: "txt"
{
"sheet_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"sheet_name": "Sheet1",
"rows": [
["ヘッダー1", "ヘッダー2", "ヘッダー3"],
["値1", "値2", "値3"],
["値4", "値5", "値6"]
],
"metadata": {
"modified_time": "2024-01-15T10:30:00Z",
"owner": "user@example.com"
}
}
{
"sheet_data": {
"rows": [...],
"formatting": {
"cell_formats": {
"A1": {"bold": true, "background_color": "#ffff00"},
"B1": {"italic": true, "text_color": "#ff0000"}
}
}
}
}