nithin81's picture
Update app.py
9f0f462 verified
Raw
History Blame Contribute Delete
8.62 kB
import streamlit as st
import pandas as pd
import numpy as np
from azure.core.credentials import AzureKeyCredential
from azure.ai.formrecognizer import DocumentAnalysisClient
import time
from dotenv import load_dotenv
import os
load_dotenv()
# Azure Form Recognizer credentials
endpoint = os.environ["endpoint"]
key = os.environ["key"]
# Initialize DocumentAnalysisClient
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
# Sidebar for document type selection
document_type = st.sidebar.selectbox(
"Select Document Type", ["Invoice", "Receipt", "Identity Document"]
)
# Center area for file upload
uploaded_file = st.file_uploader(f"Choose or drag an {document_type} file", type=["pdf", "png", "jpg", "jpeg"])
# Initialize session state for processing results
if "processed" not in st.session_state:
st.session_state.processed = False
st.session_state.tables = []
st.session_state.kv_df = pd.DataFrame()
# Process the uploaded file if the button is clicked
if uploaded_file is not None:
if st.button("Upload and Process"):
with st.spinner("Processing..."):
time.sleep(1) # Simulate some delay to show the spinner
# Analyze the document
poller = document_analysis_client.begin_analyze_document(
"prebuilt-document", document=uploaded_file
)
result = poller.result()
# Extract key-value pairs and store them in a dictionary
kv_dict = {}
for kv_pair in result.key_value_pairs:
if kv_pair.key and kv_pair.value: # Ensure both key and value exist
clean_key = kv_pair.key.content.rstrip(':')
kv_dict[clean_key] = kv_pair.value.content
kv_df = pd.DataFrame(list(kv_dict.items()), columns=["Key", "Value"]).T
# Set the first row as the header
header = kv_df.iloc[0]
# Create a new DataFrame with the header and the remaining rows
kv_df = kv_df[1:].reset_index(drop=True)
# Insert the new header row
header_df = pd.DataFrame([header], columns=range(len(header)))
# Concatenate the header row DataFrame with the original DataFrame
kv_df = pd.concat([header_df, kv_df], ignore_index=True)
st.session_state.kv_df = kv_df
st.session_state.tables = []
if result.tables:
for table in result.tables:
data = []
for cell in table.cells:
data.append([cell.row_index, cell.column_index, cell.content])
table_df = pd.DataFrame(data, columns=["row_index", "column_index", "content"])
table_df = table_df.pivot(index="row_index", columns="column_index", values="content")
# Reset the column index
table_df.reset_index(drop=True, inplace=True)
# Set the first row as header
table_df.columns = table_df.iloc[0] # Take the first row as column names
table_df = table_df.drop(table_df.index[0]) # Remove the first row after setting it as headers
# Optionally reset the index if required
table_df.reset_index(drop=True, inplace=True)
st.session_state.tables.append(table_df)
st.session_state.processed = True
# Predefine default columns in the selected table
default_columns = ['Invoice No', 'Invoice Date', 'Customer Name']
# Sidebar for table and key-value pair selection
if st.session_state.processed:
if not st.session_state.kv_df.empty:
st.sidebar.write("Key-Value Pairs found.")
else:
st.sidebar.write("No Key-Value Pairs found in document.")
if st.session_state.tables:
# Display available tables for selection in the sidebar
table_options = ["Select"] + [f"Table {i + 1}" for i in range(len(st.session_state.tables))]
selected_table_option = st.sidebar.selectbox(
"Select table to join key-value pairs:", table_options, index=0
)
# Proceed only if a table is selected
if selected_table_option != "Select":
selected_table_index = table_options.index(selected_table_option) - 1 # Adjust for "None"
selected_table_df = st.session_state.tables[selected_table_index]
# Add default columns to the left side of the table with NaN values initially
for col in default_columns:
if col not in selected_table_df.columns:
selected_table_df[col] = np.nan
# Move default columns to the left
# We include only those columns that exist in the table
existing_columns = [col for col in default_columns if col in selected_table_df.columns]
remaining_columns = [col for col in selected_table_df.columns if col not in existing_columns]
selected_table_df = selected_table_df[[*existing_columns, *remaining_columns]]
if not st.session_state.kv_df.empty:
# Allow the user to select multiple columns using checkboxes
first_row_values = st.session_state.kv_df.iloc[0].values
second_row_values = st.session_state.kv_df.iloc[1].values
key_value_options = [
f"{key}: {value}" for key, value in zip(first_row_values, second_row_values)
]
selected_columns = []
st.sidebar.write("Select key-value pairs to the default columns:")
# Create draggable interface for each key-value pair
for i, option in enumerate(key_value_options):
selected_column_option = st.sidebar.selectbox(
f"Insert {option} to the column:",
["Select"] + default_columns,
key=f"col_select_{i}"
)
if selected_column_option != "Select":
selected_columns.append((i, selected_column_option))
# Insert selected key-value pairs into the appropriate columns
for idx, selected_column in selected_columns:
st.session_state.kv_df[selected_column] = second_row_values[idx]
# Fill the column in the table with the selected key-value pair
selected_table_df[selected_column] = st.session_state.kv_df.iloc[1, idx]
st.write(f"Selected Table {selected_table_index + 1} with Key-Value Pairs Added:")
# st.dataframe(selected_table_df)
# Allow row and column selection for deletion
st.sidebar.subheader("Manage Table")
# Delete columns
if st.sidebar.checkbox("Delete Columns"):
col = list(selected_table_df.columns)
col = col[3:]
cols_to_delete = st.sidebar.multiselect(
"Select Columns to Delete", col
)
if st.sidebar.button("Remove Columns"):
st.session_state.tables[selected_table_index].drop(columns=cols_to_delete, inplace=True)
# Delete rows
if st.sidebar.checkbox("Delete Rows"):
row_indices = st.sidebar.multiselect(
"Select Rows to Delete", selected_table_df.index.tolist()
)
if st.sidebar.button("Remove Rows"):
st.session_state.tables[selected_table_index].drop(index=row_indices, inplace=True)
# Show the updated table
# st.write(f"Updated Table {selected_table_index + 1}:")
st.dataframe(selected_table_df)
# Download updated table
st.download_button(
label=f"Download Updated Table {selected_table_index + 1} as CSV",
data=selected_table_df.to_csv(index=False).encode('utf-8'),
file_name=f"updated_table_{selected_table_index + 1}.csv",
mime='text/csv',
)
else:
st.sidebar.write("No tables found in the document.")
# Option to remove the file and clear the session
if st.session_state.processed and st.sidebar.button("Remove File"):
st.session_state.processed = False
st.session_state.tables = []
st.session_state.kv_df = pd.DataFrame()
st.rerun()