Kims12 commited on
Commit
8ece039
Β·
verified Β·
1 Parent(s): a2def80

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -135
app.py CHANGED
@@ -1,163 +1,157 @@
1
  import gradio as gr
 
2
  import openpyxl
3
- from openpyxl import load_workbook
4
- from datetime import datetime
5
  import calendar
6
- import io
7
 
8
- def analyze_excel(upload_file, selected_year):
9
  """
10
- μ—…λ‘œλ“œλœ μ—‘μ…€ 파일의 데이터λ₯Ό '리뷰뢄석 원본(μˆ˜μ •).xlsx'의 '원본데이터' μ‹œνŠΈμ— μ €μž₯ν•˜κ³ ,
11
- ν•΄λ‹Ή 데이터λ₯Ό 기반으둜 'λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°' μ‹œνŠΈμ— λ―Έμ…˜λ³„ 뢄석 κ²°κ³Όλ₯Ό μž‘μ„±ν•œ ν›„
12
- λΆ„μ„λœ μ—‘μ…€ νŒŒμΌμ„ bytes ν˜•νƒœλ‘œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜.
 
 
 
 
 
 
 
13
  """
14
- # 선택년도(λ‘μžλ¦¬ λ¬Έμžμ—΄)λ₯Ό full year둜 λ³€ν™˜ (예: "25" -> 2025)
15
- full_year = 2000 + int(selected_year)
 
 
 
16
 
17
- # μ—…λ‘œλ“œλœ μ—‘μ…€ 파일(파일 객체)λ₯Ό openpyxl μ›Œν¬λΆμœΌλ‘œ λ‘œλ“œ (μ—…λ‘œλ“œ 파일의 첫번째 μ‹œνŠΈλ₯Ό μ‚¬μš©)
18
- uploaded_wb = openpyxl.load_workbook(upload_file)
19
- uploaded_ws = uploaded_wb.active
 
20
 
21
- # λ™μΌν•œ μœ„μΉ˜μ— μ‘΄μž¬ν•˜λŠ” '리뷰뢄석 원본(μˆ˜μ •).xlsx' 파일 λ‘œλ“œ
22
- main_wb = openpyxl.load_workbook("리뷰뢄석 원본(μˆ˜μ •).xlsx")
23
-
24
- # "원본데이터" μ‹œνŠΈκ°€ μ‘΄μž¬ν•˜λ©΄ μ΄ˆκΈ°ν™”, μ—†μœΌλ©΄ 생성
25
- if "원본데이터" in main_wb.sheetnames:
26
- source_ws = main_wb["원본데이터"]
27
- # κΈ°μ‘΄ 데이터λ₯Ό λͺ¨λ‘ 지움
28
- for row in source_ws.iter_rows():
29
- for cell in row:
30
- cell.value = None
31
- else:
32
- source_ws = main_wb.create_sheet("원본데이터")
33
-
34
- # μ—…λ‘œλ“œλœ μ—‘μ…€ 파일의 데이터λ₯Ό "원본데이터" μ‹œνŠΈμ— κ·ΈλŒ€λ‘œ 볡사
35
- for row in uploaded_ws.iter_rows(values_only=True):
36
- source_ws.append(row)
37
-
38
- # "원본데이터" μ‹œνŠΈμ˜ Bμ—΄(리뷰 λ‚ μ§œ)을 κΈ°μ€€μœΌλ‘œ 데이터λ₯Ό 읽음 (첫번째 행은 header둜 κ°€μ •)
39
- review_dates = []
40
- for row in source_ws.iter_rows(min_row=2, min_col=2, max_col=2, values_only=True):
41
- cell_value = row[0]
42
- if cell_value is None:
43
- continue
44
- # μ…€μ˜ 값이 datetime 객체인지 확인, μ•„λ‹ˆλ©΄ λ¬Έμžμ—΄λ‘œ κ°€μ •ν•˜μ—¬ νŒŒμ‹±
45
- if isinstance(cell_value, datetime):
46
- review_date = cell_value
47
- else:
48
- try:
49
- # μ˜ˆμ‹œ: "25.02.25" ν˜•μ‹
50
- review_date = datetime.strptime(str(cell_value).strip(), "%y.%m.%d")
51
- except Exception as e:
52
- # λŒ€μ²΄ ν˜•μ‹ (예: "2025-02-25")둜 μ‹œλ„
53
- try:
54
- review_date = datetime.strptime(str(cell_value).strip(), "%Y-%m-%d")
55
- except Exception as e:
56
- continue
57
- review_dates.append(review_date)
58
-
59
- # ν˜„μž¬ λ‚ μ§œ κΈ°μ€€μœΌλ‘œ 졜근 3λ…„ (current_year-2, current_year-1, current_year) 계산
60
- today = datetime.today()
61
- current_year = today.year
62
- recent_years = [current_year - 2, current_year - 1, current_year]
63
 
64
- # λ―Έμ…˜2: 졜근 3λ…„μ˜ 월별 좔이(리뷰건수) 계산
65
- monthly_counts = []
66
- for yr in recent_years:
67
- for m in range(1, 13):
68
- count = sum(1 for d in review_dates if d.year == yr and d.month == m)
69
- monthly_counts.append(count)
70
 
71
- # "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈκ°€ μ‘΄μž¬ν•˜λ©΄ μ‚¬μš©, μ—†μœΌλ©΄ 생성
72
- if "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" in main_wb.sheetnames:
73
- dashboard_ws = main_wb["λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°"]
74
- else:
75
- dashboard_ws = main_wb.create_sheet("λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°")
76
 
77
- # λ―Έμ…˜2: 월별 리뷰 건수λ₯Ό "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ C5μ…€λΆ€ν„° C40셀에 μž…λ ₯ (총 36μ…€)
78
- row_idx = 5
79
- for count in monthly_counts:
80
- dashboard_ws.cell(row=row_idx, column=3, value=count) # μ—΄ C = 3번째 μ—΄
81
- row_idx += 1
 
 
82
 
83
- # λ―Έμ…˜3: 졜근 3λ…„μ˜ 년도별 리뷰 건수 계산 및 "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ F5, F6, F7에 μž…λ ₯
84
- yearly_counts = {}
85
- for yr in recent_years:
86
- yearly_counts[yr] = sum(1 for d in review_dates if d.year == yr)
87
- # λ‚΄λ¦Όμ°¨μˆœ: ν˜„μž¬λ…„λ„λΆ€ν„° κ°€μž₯ 였래된 년도 순으둜
88
- dashboard_ws["F5"] = yearly_counts.get(current_year, 0)
89
- dashboard_ws["F6"] = yearly_counts.get(current_year - 1, 0)
90
- dashboard_ws["F7"] = yearly_counts.get(current_year - 2, 0)
91
-
92
- # ν˜„μž¬ 년도(λ‘μžλ¦¬)λ₯Ό "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ E2셀에 μž…λ ₯ (예: 2025 -> "25")
93
- dashboard_ws["E2"] = str(current_year % 100).zfill(2)
 
 
 
 
 
 
 
 
94
 
95
- # λ―Έμ…˜4: μ„ νƒλœ λ…„λ„μ˜ 월별 리뷰 건수 계산 및 "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ I5μ…€λΆ€ν„° I16셀에 μž…λ ₯
96
- selected_monthly_counts = []
97
- for m in range(1, 13):
98
- count = sum(1 for d in review_dates if d.year == full_year and d.month == m)
99
- selected_monthly_counts.append(count)
100
- row_idx = 5
101
- for count in selected_monthly_counts:
102
- dashboard_ws.cell(row=row_idx, column=9, value=count) # μ—΄ I = 9번째 μ—΄
103
- row_idx += 1
 
 
 
 
 
 
104
 
105
- # λ―Έμ…˜5: μ„ νƒλœ λ…„λ„μ˜ 월일별(1μ›”01일 ~ 12μ›”31일) 리뷰 건수 계산 및 "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ L5μ…€λΆ€ν„° L369셀에 μž…λ ₯
106
- # 단, μ„ νƒλœ 년도가 μœ€λ…„μΈ κ²½μš°μ—λ„ 365μ…€ (2μ›”29일은 μ œμ™Έ)
107
- selected_daily_counts = []
108
- for m in range(1, 13):
109
- # ν•΄λ‹Ή μ›”μ˜ λ§ˆμ§€λ§‰ λ‚ μ§œ (2μ›”μ˜ 경우 μœ€λ…„μ΄λ©΄ 29μΌμ΄μ§€λ§Œ 29일은 μ œμ™Έν•˜μ—¬ 28μΌκΉŒμ§€λ§Œ 계산)
110
- last_day = calendar.monthrange(full_year, m)[1]
111
- if m == 2 and last_day == 29:
112
- last_day = 28
113
- for d in range(1, last_day + 1):
114
- count = sum(1 for dt in review_dates if dt.year == full_year and dt.month == m and dt.day == d)
115
- selected_daily_counts.append(count)
116
- row_idx = 5
117
- for count in selected_daily_counts:
118
- dashboard_ws.cell(row=row_idx, column=12, value=count) # μ—΄ L = 12번째 μ—΄
119
- row_idx += 1
120
 
121
- # μ„ νƒλœ λ…„λ„μ˜ λ‘μžλ¦¬ 값을 "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈ K2셀에 μž…λ ₯ (예: 2024 -> "24")
122
- dashboard_ws["K2"] = str(full_year % 100).zfill(2)
123
-
124
- # λ³€κ²½λœ μ›Œν¬λΆμ„ BytesIO에 μ €μž₯ ν›„ bytes 데이터λ₯Ό λ°˜ν™˜
125
- output = io.BytesIO()
126
- main_wb.save(output)
127
  output.seek(0)
128
- return output.getvalue()
 
 
129
 
130
  def get_year_options():
131
  """
132
- ν˜„μž¬λ…„λ„ κΈ°μ€€ 졜근 5λ…„(예: 2025년이면 25, 24, 23, 22, 21)의 μ˜΅μ…˜μ„ λ‘μžλ¦¬ λ¬Έμžμ—΄λ‘œ λ°˜ν™˜
 
133
  """
134
- current_year = datetime.today().year
135
- options = [str((current_year - i) % 100).zfill(2) for i in range(0, 5)]
 
136
  return options
137
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  with gr.Blocks() as demo:
139
- gr.Markdown("## 리뷰뢄석 μ—‘μ…€ 파일 뢄석 슀페이슀")
140
  with gr.Row():
141
- file_input = gr.File(label="원본 μ—‘μ…€ 파일 μ—…λ‘œλ“œ", file_types=[".xlsx"])
142
  year_dropdown = gr.Dropdown(label="뢄석년도 선택", choices=get_year_options(), value=get_year_options()[0])
143
- analyze_button = gr.Button("뢄석")
144
- download_output = gr.File(label="λΆ„μ„λœ μ—‘μ…€ 파일 λ‹€μš΄λ‘œλ“œ")
145
-
146
- def process(file_obj, selected_year):
147
- if file_obj is None:
148
- return None
149
- # Gradio File μ»΄ν¬λ„ŒνŠΈλ‘œ μ—…λ‘œλ“œλœ νŒŒμΌμ€ file_obj['name'] 경둜λ₯Ό 가짐.
150
- with open(file_obj.name, "rb") as f:
151
- file_bytes = f.read()
152
- # BytesIO 객체둜 λ³€ν™˜ν•˜μ—¬ 뢄석 ν•¨μˆ˜ 호좜
153
- result_bytes = analyze_excel(io.BytesIO(file_bytes), selected_year)
154
- # 뢄석 κ²°κ³Όλ₯Ό μž„μ‹œ 파일("뢄석결과.xlsx")둜 μ €μž₯ν•˜μ—¬ λ‹€μš΄λ‘œλ“œ κ°€λŠ₯ν•˜λ„λ‘ 함
155
- output_path = "뢄석결과.xlsx"
156
- with open(output_path, "wb") as out_f:
157
- out_f.write(result_bytes)
158
- return output_path
159
-
160
- analyze_button.click(fn=process, inputs=[file_input, year_dropdown], outputs=download_output)
161
 
162
  if __name__ == "__main__":
163
  demo.launch()
 
1
  import gradio as gr
2
+ import pandas as pd
3
  import openpyxl
4
+ from openpyxl.utils import get_column_letter
5
+ import datetime
6
  import calendar
7
+ from io import BytesIO
8
 
9
+ def process_file(uploaded_file, selected_year):
10
  """
11
+ 1. μ—…λ‘œλ“œλœ 원본 μ—‘μ…€ νŒŒμΌμ„ 읽어 DataFrame으둜 λ³€ν™˜ν•©λ‹ˆλ‹€.
12
+ 2. λ™μΌν•œ μœ„μΉ˜μ— μžˆλŠ” ν…œν”Œλ¦Ώ 파일 "리뷰뢄석.ver1.0"을 λΆˆλŸ¬μ˜΅λ‹ˆλ‹€.
13
+ 3. ν…œν”Œλ¦Ώ λ‚΄ "원본데이터" μ‹œνŠΈμ— μ—…λ‘œλ“œλœ 데이터λ₯Ό κ·ΈλŒ€λ‘œ κΈ°λ‘ν•©λ‹ˆλ‹€.
14
+ 4. μ—…λ‘œλ“œ λ°μ΄ν„°μ˜ 리뷰 λ‚ μ§œ(Bμ—΄)λ₯Ό 기반으둜 μ—¬λŸ¬ λ―Έμ…˜μ— ν•΄λ‹Ήν•˜λŠ” 집계(졜근 3λ…„ 월별/년도별, 선택년도 월별/월일별)λ₯Ό μˆ˜ν–‰ν•˜μ—¬
15
+ "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈμ˜ μ§€μ • 셀에 결과값을 κΈ°λ‘ν•©λ‹ˆλ‹€.
16
+ - λ―Έμ…˜2: 졜근 3λ…„μ˜ 각 년도(예: 23,24,25)와 각 월별 리뷰 건수λ₯Ό C5 ~ C40 셀에 κΈ°λ‘ν•©λ‹ˆλ‹€.
17
+ - λ―Έμ…˜3: 졜근 3λ…„μ˜ 연도별 리뷰 건수λ₯Ό F5(ν˜„μž¬λ…„λ„), F6(전년도), F7(전전년도)에 κΈ°λ‘ν•˜κ³ , ν˜„μž¬λ…„λ„(λ‘μžλ¦¬)λ₯Ό E2셀에 μž…λ ₯ν•©λ‹ˆλ‹€.
18
+ - λ―Έμ…˜4: λ“œλ‘­λ‹€μš΄μœΌλ‘œ μ„ νƒλœ 년도(졜근 5λ…„ 쀑 ν•˜λ‚˜)의 월별 리뷰 건수λ₯Ό I5 ~ I16 셀에 κΈ°λ‘ν•©λ‹ˆλ‹€.
19
+ - λ―Έμ…˜5: μ„ νƒλœ λ…„λ„μ˜ 1μ›”1일뢀터 12μ›”31μΌκΉŒμ§€(365일 κΈ°μ€€) 일별 리뷰 건수λ₯Ό L5 ~ L369 셀에 κΈ°λ‘ν•˜κ³ , 선택년도(λ‘μžλ¦¬)λ₯Ό K2셀에 μž…λ ₯ν•©λ‹ˆλ‹€.
20
+ 5. μ΅œμ’… μˆ˜μ •λœ μ›Œν¬λΆμ„ BytesIO 객체둜 μ €μž₯ν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€.
21
  """
22
+ # μ—…λ‘œλ“œλœ μ—‘μ…€ νŒŒμΌμ„ pandas DataFrame으둜 읽기 (첫번째 μ‹œνŠΈλ₯Ό μ‚¬μš©)
23
+ df = pd.read_excel(uploaded_file, engine="openpyxl")
24
+ # 리뷰 λ‚ μ§œλŠ” μ—…λ‘œλ“œ 파일의 λ‘λ²ˆμ§Έ μ—΄(Bμ—΄)둜 κ°€μ •ν•˜κ³ , λ‚ μ§œ ν˜•μ‹μœΌλ‘œ λ³€ν™˜
25
+ review_date_col = df.columns[1]
26
+ df[review_date_col] = pd.to_datetime(df[review_date_col], errors='coerce')
27
 
28
+ # ν…œν”Œλ¦Ώ 파일 "리뷰뢄석.ver1.0" 뢈러였기 (동일 κ²½λ‘œμ— μœ„μΉ˜)
29
+ wb = openpyxl.load_workbook("리뷰뢄석.ver1.0")
30
+ ws_origin = wb["원본데이터"]
31
+ ws_dashboard = wb["λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°"]
32
 
33
+ # [λ―Έμ…˜ 1] μ—…λ‘œλ“œλœ 자료λ₯Ό "원본데이터" μ‹œνŠΈμ— λ™μΌν•˜κ²Œ μ €μž₯
34
+ # κΈ°μ‘΄ 데이터 μ‚­μ œ (μ…€ λ‚΄μš© λͺ¨λ‘ μ΄ˆκΈ°ν™”)
35
+ for row in ws_origin.iter_rows(min_row=1, max_row=ws_origin.max_row, min_col=1, max_col=ws_origin.max_column):
36
+ for cell in row:
37
+ cell.value = None
38
+ # DataFrame의 헀더 및 데이터λ₯Ό μˆœμ„œλŒ€λ‘œ 기둝 (μ—‘μ…€μ˜ A1μ…€λΆ€ν„° 기둝)
39
+ for col_idx, col_name in enumerate(df.columns, start=1):
40
+ ws_origin.cell(row=1, column=col_idx, value=col_name)
41
+ for row_idx, row in df.iterrows():
42
+ for col_idx, value in enumerate(row, start=1):
43
+ ws_origin.cell(row=row_idx+2, column=col_idx, value=value)
44
+
45
+ # 집계 처리λ₯Ό μœ„ν•΄ 리뷰 λ‚ μ§œκ°€ μžˆλŠ” ν–‰λ§Œ 필터링
46
+ df_dates = df.dropna(subset=[review_date_col]).copy()
47
+ df_dates[review_date_col] = pd.to_datetime(df_dates[review_date_col], errors='coerce')
48
+ df_dates = df_dates.dropna(subset=[review_date_col])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ # ν˜„μž¬λ…„λ„ 정보 (예: 2025λ…„ β†’ λ‘μžλ¦¬ 25)
51
+ current_full_year = datetime.datetime.now().year
52
+ current_two_digit = int(str(current_full_year)[-2:])
 
 
 
53
 
54
+ # [λ―Έμ…˜ 2,3] 졜근 3λ…„: (ν˜„μž¬λ…„λ„, 전년도, 전전년도)
55
+ recent_years_full = [current_full_year - i for i in range(2, -1, -1)] # 예: [2023, 2024, 2025]
 
 
 
56
 
57
+ # λ―Έμ…˜2: 졜근 3λ…„μ˜ 월별 리뷰 건수 집계 (각 년도별 1μ›”~12μ›”)
58
+ df_recent = df_dates[df_dates[review_date_col].dt.year >= (current_full_year - 2)]
59
+ month_counts = {}
60
+ for year in recent_years_full:
61
+ for month in range(1, 13):
62
+ count = df_recent[(df_recent[review_date_col].dt.year == year) & (df_recent[review_date_col].dt.month == month)].shape[0]
63
+ month_counts[(year, month)] = count
64
 
65
+ # "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈμ˜ C5μ…€λΆ€ν„° C40μ…€κΉŒμ§€ μˆœμ„œλŒ€λ‘œ 기둝 (첫 12μ…€: 전전년도, κ·Έ λ‹€μŒ: 전년도, λ§ˆμ§€λ§‰ 12μ…€: ν˜„μž¬λ…„λ„)
66
+ start_row = 5
67
+ col_month = 3 # Cμ—΄
68
+ for year in recent_years_full:
69
+ for month in range(1, 13):
70
+ ws_dashboard.cell(row=start_row, column=col_month, value=month_counts.get((year, month), 0))
71
+ start_row += 1
72
+
73
+ # λ―Έμ…˜3: 졜근 3λ…„μ˜ 연도별 리뷰 건수 집계 및 기둝
74
+ year_counts = {}
75
+ for year in recent_years_full:
76
+ count = df_recent[df_recent[review_date_col].dt.year == year].shape[0]
77
+ year_counts[year] = count
78
+ # "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈμ˜ F5셀에 ν˜„μž¬λ…„λ„, F6셀에 전년도, F7셀에 전전년도 건수 μž…λ ₯
79
+ ws_dashboard.cell(row=5, column=6, value=year_counts.get(current_full_year, 0)) # F5: ν˜„μž¬λ…„λ„
80
+ ws_dashboard.cell(row=6, column=6, value=year_counts.get(current_full_year - 1, 0)) # F6: 전년도
81
+ ws_dashboard.cell(row=7, column=6, value=year_counts.get(current_full_year - 2, 0)) # F7: 전전년도
82
+ # ν˜„μž¬λ…„λ„(λ‘μžλ¦¬)λ₯Ό E2셀에 μž…λ ₯
83
+ ws_dashboard.cell(row=2, column=5, value=str(current_two_digit))
84
 
85
+ # [λ―Έμ…˜ 4] μ„ νƒλœ λ…„λ„μ˜ 월별 리뷰 건수 집계
86
+ # λ“œλ‘­λ‹€μš΄μœΌλ‘œ μ„ νƒλœ 값은 λ‘μžλ¦¬ λ¬Έμžμ—΄ (예: "25") β†’ full year 계산
87
+ selected_year_int = int(selected_year)
88
+ full_selected_year = current_full_year - ((current_two_digit) - selected_year_int)
89
+ df_selected = df_dates[df_dates[review_date_col].dt.year == full_selected_year]
90
+ month_counts_selected = {}
91
+ for month in range(1, 13):
92
+ count = df_selected[df_selected[review_date_col].dt.month == month].shape[0]
93
+ month_counts_selected[month] = count
94
+ # "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈμ˜ I5μ…€λΆ€ν„° I16μ…€κΉŒμ§€ 기둝 (1μ›” ~ 12μ›”)
95
+ start_row = 5
96
+ col_selected_month = 9 # Iμ—΄
97
+ for month in range(1, 13):
98
+ ws_dashboard.cell(row=start_row, column=col_selected_month, value=month_counts_selected.get(month, 0))
99
+ start_row += 1
100
 
101
+ # [λ―Έμ…˜ 5] μ„ νƒλœ λ…„λ„μ˜ 월일별 리뷰 건수 집계 (1μ›” 1일 ~ 12μ›” 31일: 총 365일)
102
+ day_counts_selected = []
103
+ for month in range(1, 13):
104
+ num_days = calendar.monthrange(full_selected_year, month)[1]
105
+ for day in range(1, num_days + 1):
106
+ count = df_selected[(df_selected[review_date_col].dt.month == month) & (df_selected[review_date_col].dt.day == day)].shape[0]
107
+ day_counts_selected.append(count)
108
+ # "λŒ€μ‹œλ³΄λ“œλ°μ΄ν„°" μ‹œνŠΈμ˜ L5μ…€λΆ€ν„° L369μ…€κΉŒμ§€ 기둝
109
+ start_row = 5
110
+ col_selected_day = 12 # Lμ—΄
111
+ for count in day_counts_selected:
112
+ ws_dashboard.cell(row=start_row, column=col_selected_day, value=count)
113
+ start_row += 1
114
+ # μ„ νƒλœ λ…„λ„μ˜ λ‘μžλ¦¬ 값을 K2셀에 μž…λ ₯
115
+ ws_dashboard.cell(row=2, column=11, value=str(selected_year_int))
116
 
117
+ # μ΅œμ’… μˆ˜μ •λœ μ›Œν¬λΆμ„ BytesIO 객체에 μ €μž₯ν•˜μ—¬ λ°˜ν™˜
118
+ output = BytesIO()
119
+ wb.save(output)
 
 
 
120
  output.seek(0)
121
+ # λ°˜ν™˜ νŒŒμΌμ— 파일λͺ…을 μ§€μ • (λ‹€μš΄λ‘œλ“œ μ‹œ μ‚¬μš©)
122
+ output.name = "리뷰뢄석_λ³΄κ³ μ„œ.xlsx"
123
+ return output
124
 
125
  def get_year_options():
126
  """
127
+ λ“œλ‘­λ‹€μš΄μ˜ 선택 ν•­λͺ©μ„ 졜근 5λ…„(ν˜„μž¬λ…„λ„λΆ€ν„° μ „4λ…„)으둜 μƒμ„±ν•©λ‹ˆλ‹€.
128
+ 예λ₯Ό λ“€μ–΄, ν˜„μž¬λ…„λ„ 2025년이면 μ˜΅μ…˜μ€ "25", "24", "23", "22", "21"이 λ©λ‹ˆλ‹€.
129
  """
130
+ current_full_year = datetime.datetime.now().year
131
+ current_two_digit = int(str(current_full_year)[-2:])
132
+ options = [str(current_two_digit - i) for i in range(0, 5)]
133
  return options
134
 
135
+ def generate_report(file, selected_year):
136
+ # 파일 μ—…λ‘œλ“œκ°€ μ—†μœΌλ©΄ None λ°˜ν™˜
137
+ if file is None:
138
+ return None
139
+ # gr.File μ—…λ‘œλ“œ μ‹œ file은 dict ν˜•νƒœλ‘œ {"name": ..., "data": ...}둜 전달됨
140
+ if isinstance(file, dict):
141
+ file_obj = BytesIO(file["data"])
142
+ else:
143
+ file_obj = file
144
+ output_bytes = process_file(file_obj, selected_year)
145
+ return output_bytes
146
+
147
  with gr.Blocks() as demo:
148
+ gr.Markdown("## 리뷰뢄석 λ³΄κ³ μ„œ 생성 슀페이슀")
149
  with gr.Row():
150
+ file_input = gr.File(label="원본 μ—‘μ…€ 파일 μ—…λ‘œλ“œ", file_types=[".xlsx", ".xls"])
151
  year_dropdown = gr.Dropdown(label="뢄석년도 선택", choices=get_year_options(), value=get_year_options()[0])
152
+ output_file = gr.File(label="μƒμ„±λœ λ³΄κ³ μ„œ λ‹€μš΄λ‘œλ“œ")
153
+ generate_button = gr.Button("λ³΄κ³ μ„œ 생성")
154
+ generate_button.click(fn=generate_report, inputs=[file_input, year_dropdown], outputs=output_file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  if __name__ == "__main__":
157
  demo.launch()