You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
13 KiB
Python

import subprocess
import openpyxl
from openpyxl.utils import get_column_letter
from openpyxl.styles import PatternFill
from datetime import datetime
import time
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from config import get_connection
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
file_ref = f"{ROOT_DIR}/wlc.xlsx"
file_hasil = f"{ROOT_DIR}/hasil/wlc.xlsx"
start_time = time.time()
conn = get_connection()
if conn is None:
print("Koneksi ke database gagal.")
sys.exit(1)
cur = conn.cursor()
# Fungsi untuk mengambil data dari PostgreSQL
def fetch_data_from_postgresql(q=""):
try:
cur.execute(q) # Jalankan query yang diberikan
col_names = [desc[0] for desc in cur.description] # Ambil nama kolom
rows = cur.fetchall() # Ambil semua baris data
# Buat list dictionary berdasarkan nama kolom
result = [dict(zip(col_names, row)) for row in rows]
return result
except Exception as e:
print(f"Error: {e}")
return None
def insert_and_shift_right(file_path, sheet_name):
# Load workbook and select sheet
wb = openpyxl.load_workbook(file_path)
sheet = wb[sheet_name]
# Get the last two columns
max_col = sheet.max_column
last_two_cols = [max_col - 1, max_col]
# Insert a new column after the last two columns
new_col_idx = max_col + 1
sheet.insert_cols(new_col_idx)
# Shift formulas, values, and styles
for row in range(1, sheet.max_row + 1):
for col in last_two_cols:
current_cell = sheet.cell(row=row, column=col)
current_value = current_cell.value
if isinstance(current_value, str) and current_value.startswith("="):
# Adjust formula to the new column
formula = current_value.replace(get_column_letter(col), get_column_letter(new_col_idx))
sheet.cell(row=row, column=new_col_idx, value=formula)
else:
sheet.cell(row=row, column=new_col_idx, value=current_value)
# Copy cell style (fill color)
new_cell = sheet.cell(row=row, column=new_col_idx)
if current_cell.fill:
new_cell.fill = PatternFill(start_color=current_cell.fill.start_color.rgb,
end_color=current_cell.fill.end_color.rgb,
fill_type=current_cell.fill.fill_type)
# Save workbook with changes
wb.save(file_path)
print(f"Column inserted and shifted to the right in {file_path}")
def insert_column_data(file_path, sheet_name, col_name, data):
"""
Memasukkan data ke Excel per kolom.
Args:
file_path (str): Path file Excel.
sheet_name (str): Nama sheet Excel.
col_name (str): Nama kolom untuk dicari di baris pertama.
data (dict): Data yang akan dimasukkan, dengan kunci adalah baris (row_name) dan nilai adalah isi sel.
"""
# Load workbook dan pilih sheet
wb = openpyxl.load_workbook(file_path, data_only=False)
sheet = wb[sheet_name]
# Temukan indeks kolom berdasarkan col_name di baris pertama
col_index = None
for col in range(1, sheet.max_column + 1):
if sheet.cell(row=1, column=col).value == col_name:
col_index = col
break
# Jika kolom ditemukan, masukkan data per baris
if col_index:
for row_name, value in data.items():
row_index = None
# Cari indeks baris berdasarkan nama di kolom pertama
for row in range(2, sheet.max_row + 1): # Mulai dari baris ke-2 untuk menghindari header
if sheet.cell(row=row, column=1).value == row_name:
row_index = row
break
# Isi nilai jika baris ditemukan
if row_index:
sheet.cell(row=row_index, column=col_index, value=value)
else:
print(f"Column name '{col_name}' not found in the sheet.")
# Simpan workbook setelah semua data kolom dimasukkan
wb.save(file_path)
wb.close()
wb.save(file_path)
def insert_param(file_path):
wb = openpyxl.load_workbook(file_path, data_only=False)
sheet = wb["Params"]
col_name = "Value"
# Temukan indeks kolom berdasarkan col_name di baris pertama
col_index = None
for col in range(1, sheet.max_column + 1):
if sheet.cell(row=1, column=col).value == col_name:
col_index = col
break
query = """SELECT
value_str,
CASE
WHEN unit_of_measurement = '%' THEN value_num / 100
ELSE value_num
END AS value_num
FROM lcc_ms_master"""
data_map = fetch_data_from_postgresql(query)
mapping_data = {}
for item in data_map:
mapping_data[item['value_str']] = round(item['value_num'], 2)
# Jika kolom ditemukan, masukkan data per baris
if col_index:
for row in range(2, sheet.max_row + 1): # Mulai dari baris ke-2 untuk menghindari header
param_name = sheet.cell(row=row, column=1).value # Kolom 1 == value_str
if param_name in mapping_data:
sheet.cell(row=row, column=col_index, value=mapping_data[param_name])
else:
print(f"Params: Baris name '{col_name}' not found in the sheet.")
# Simpan workbook setelah semua data diperbarui
wb.save(file_path)
wb.close()
def get_abjad(i):
if i < 0:
raise ValueError("Indeks harus berupa angka 0 atau lebih.")
result = ""
while i >= 0:
i, remainder = divmod(i, 26)
result = chr(65 + remainder) + result
i -= 1 # Mengurangi 1 untuk menangani offset ke basis 0
return result
def validate_number(n):
return n if n is not None else 0
# Example usage
# insert_and_shift_right(file_ref, "Calc")
# ====================================================== 00000 =================================================
# =============================================== SET DATA KE EXCEL =================================================
# ====================================================== 00000 =================================================
# insert PARAM
insert_param(file_ref)
print("Insert Params Sukses")
# Pengolahan data dari PostgreSQL
current_year = datetime.now().year
query = "SELECT * FROM lcc_plant_tr_data ORDER BY seq"
data = fetch_data_from_postgresql(query)
if data:
for record in data:
# print(f"Processing column for year {record['tahun']}")
# Kumpulkan semua data untuk satu kolom
col_data = {}
# Tambahkan data tambahan berdasarkan kondisi
if record['is_actual'] == 1:
col_data.update({
"Net Capacity Factor": validate_number(record['net_capacity_factor']),
"EAF": validate_number(record['eaf']),
"Biaya Investasi Tambahan": validate_number(record['cost_a_pinjaman'])/1000000,
"O & M Cost": validate_number(record['cost_bd_om'])/1000000,
"Periodic Maintenance Cost (Non MI)": validate_number(record['cost_bd_pm_nonmi'])/1000000,
"Production (Bruto)": validate_number(record['production_bruto']),
"Production (Netto)": validate_number(record['production_netto']),
"Fuel Consumption": validate_number(record['fuel_consumption']),
"Revenue A": validate_number(record['revenue_a'])/1000000,
"Revenue B": validate_number(record['revenue_b'])/1000000,
"Revenue C": validate_number(record['revenue_c'])/1000000,
"Revenue D": validate_number(record['revenue_d'])/1000000,
"Fuel Cost": validate_number(record['cost_c_fuel'])/1000000
})
else:
seq_offset = record['seq'] + 2
col_data.update({
"Net Capacity Factor": validate_number(record['net_capacity_factor']),
"EAF": validate_number(record['eaf']),
"Biaya Investasi Tambahan": validate_number(record['cost_a_pinjaman'])/1000000,
"O & M Cost": validate_number(record['cost_bd_om'])/1000000,
"Periodic Maintenance Cost (Non MI)": validate_number(record['cost_bd_pm_nonmi'])/1000000,
"Production (Bruto)": f"={get_abjad(seq_offset)}7/(100-SUM(Params!$C$16:$C$17))*100",
"Production (Netto)": f"={get_abjad(seq_offset)}4*8760*Params!$C$15/100",
"Fuel Consumption": f"={get_abjad(seq_offset)}6*Params!$C$18",
"Revenue A": f"=(Params!$C$19*{get_abjad(seq_offset)}5*Params!$C$15*1000*12/100)/1000000",
"Revenue B": f"=(Params!$C$20*{get_abjad(seq_offset)}5*Params!$C$15*1000*12/100)/1000000",
"Revenue C": f"=Params!$C$21*{get_abjad(seq_offset)}7*1000/1000000",
"Revenue D": f"=Params!$C$22*{get_abjad(seq_offset)}7*1000/1000000",
"Fuel Cost": f"={get_abjad(seq_offset)}9*Params!$C$23/10^6"
})
# Masukkan data ke Excel
insert_column_data(file_ref, "Calc", record['tahun'], col_data)
else:
print("No data found.")
# ====================================================== 00000 =================================================
# =============================================== SIMPAN UNTUK CHART =================================================
# ====================================================== 00000 =================================================
# Mapping dari kolom Excel ke nama kolom database sesuai gambar 2
libreoffice_path = "soffice" # Sesuaikan dengan lokasi di Linux/Windows
command = f'"{libreoffice_path}" --headless --convert-to xlsx {file_ref} --outdir {ROOT_DIR}/hasil'
subprocess.run(command, shell=True, check=True)
print("recalculate OK")
# def read_excel_with_pandas(file_path, sheet_name):
# df = pd.read_excel(file_path, sheet_name=sheet_name, engine='openpyxl')
# print(df.head()) # Periksa apakah nilai diambil dengan benar
# read_excel_with_pandas(f"{file_hasil}", "Upload")
#
column_mapping = {
"Total Revenue": "chart_total_revenue",
"Revenue A": "chart_revenue_a",
"Revenue B": "chart_revenue_b",
"Revenue C": "chart_revenue_c",
"Revenue D": "chart_revenue_d",
"Revenue Annualized": "chart_revenue_annualized",
"Fuel Cost (Component C)": "chart_fuel_cost_component_c",
"Fuel Cost": "chart_fuel_cost",
"Fuel Cost Annualized": "chart_fuel_cost_annualized",
"O and M Cost (Component B and D)": "chart_oem_component_bd",
"O and M Cost": "chart_oem_bd_cost",
"Periodic Maintenance Cost (NonMI)": "chart_oem_periodic_maintenance_cost",
"O and M Cost Annualized": "chart_oem_annualized",
"Capex (Component A)": "chart_capex_component_a",
"Biaya Investasi Tambahan": "chart_capex_biaya_investasi_tambahan",
"Acquisition Cost": "chart_capex_acquisition_cost",
"Capex Annualized": "chart_capex_annualized"
}
# Fungsi untuk memperbarui database
def update_database_from_excel():
# Buka koneksi ke PostgreSQL
try:
# Load workbook dan pilih sheet
wb = openpyxl.load_workbook(f"{file_hasil}", data_only=True)
sheet = wb["Upload"]
# Ambil tahun dari baris pertama mulai dari kolom ketiga
years = [sheet.cell(row=1, column=col).value for col in range(3, sheet.max_column + 1)]
# Loop melalui setiap baris di Excel mulai dari baris kedua
for row in range(2, sheet.max_row + 1):
row_name = sheet.cell(row=row, column=1).value # Nama data di kolom pertama
row_name = row_name if row_name else sheet.cell(row=row,column=2).value # Nama data di kolom kedua jika kolom pertama kosong
db_column = column_mapping.get(row_name)
if db_column:
for col_index, year in enumerate(years, start=3): # Iterasi mulai dari kolom ke-3
value = sheet.cell(row=row, column=col_index).value
if value is None:
continue
# Lakukan update data ke database
query = f"""
UPDATE lcc_plant_tr_data
SET {db_column} = %s
WHERE tahun = %s
"""
seq = sheet.cell(row=row, column=2).value # Ambil seq dari kolom kedua jika dibutuhkan
cur.execute(query, (value, year)) # Jalankan query dengan parameter
conn.commit()
print("Data successfully updated in database.")
except Exception as e:
conn.rollback()
print(f"Error: {e}")
update_database_from_excel()
cur.close()
conn.close()
end_time = time.time()
elapsed_time = end_time - start_time
minutes = int(elapsed_time // 60)
seconds = int(elapsed_time % 60)
# Cetak hasil
print(f"Execution time: {minutes} minutes and {seconds} seconds")