DSatishchandra commited on
Commit
9871ade
1 Parent(s): ea15866

Create BHEL.py

Browse files
Files changed (1) hide show
  1. BHEL.py +110 -0
BHEL.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pdfplumber
2
+ import pandas as pd
3
+ import re
4
+ import gradio as gr
5
+
6
+ def extract_data(pdf_file):
7
+ """
8
+ Extract data from the uploaded PDF for dynamic ranges (e.g., 10 to n).
9
+ """
10
+ data = []
11
+ columns = ["SI No", "Material Description", "Unit", "Quantity", "Dely Qty", "Dely Date", "Unit Rate", "Value"]
12
+
13
+ start_si = 10 # Start from SI No 10
14
+ end_si = None # Dynamically detect the end SI No
15
+
16
+ with pdfplumber.open(pdf_file) as pdf:
17
+ for page in pdf.pages:
18
+ full_text = page.extract_text() # Get the text content for the page
19
+ lines = full_text.splitlines() if full_text else []
20
+
21
+ for line in lines:
22
+ try:
23
+ # Parse the first column for SI No
24
+ si_no_match = re.match(r"^\s*(\d+)\s", line)
25
+ if not si_no_match:
26
+ continue
27
+
28
+ si_no = int(si_no_match.group(1))
29
+ # Dynamically set the end SI No if higher SI Nos are found
30
+ if end_si is None or si_no > end_si:
31
+ end_si = si_no
32
+
33
+ if si_no < start_si:
34
+ continue # Skip rows below the start SI No
35
+
36
+ # Extract Material Description and details dynamically
37
+ material_desc = extract_material_description(full_text, si_no)
38
+
39
+ # Extract remaining fields
40
+ parts = line.split()
41
+ unit = parts[3]
42
+ quantity = int(parts[4])
43
+ dely_qty = int(parts[5])
44
+ dely_date = parts[6]
45
+ unit_rate = float(parts[7])
46
+ value = float(parts[8])
47
+
48
+ # Append row data
49
+ data.append([si_no, material_desc, unit, quantity, dely_qty, dely_date, unit_rate, value])
50
+
51
+ except (ValueError, IndexError):
52
+ # Skip invalid rows or rows with missing data
53
+ continue
54
+
55
+ # Convert data to DataFrame and save as Excel
56
+ df = pd.DataFrame(data, columns=columns)
57
+ excel_path = "/tmp/Extracted_PO_Data_Dynamic.xlsx"
58
+ df.to_excel(excel_path, index=False)
59
+ return excel_path
60
+
61
+ def extract_material_description(full_text, si_no):
62
+ """
63
+ Extract Material Description, including Material Number, HSN Code, and IGST, using unique patterns.
64
+ """
65
+ material_desc = ""
66
+
67
+ # Match the specific SI No row to extract details
68
+ si_no_pattern = rf"{si_no}\s+(BPS\s+\d+).*?Material\s+Number:\s+(\d+)"
69
+ match = re.search(si_no_pattern, full_text, re.DOTALL)
70
+ if match:
71
+ bps_code = match.group(1)
72
+ material_number = match.group(2)
73
+ material_desc += f"{bps_code}\nMaterial Number: {material_number}\n"
74
+
75
+ # Extract HSN Code
76
+ hsn_code_match = re.search(r"HSN\s+Code:\s*(\d+)", full_text)
77
+ if hsn_code_match:
78
+ hsn_code = hsn_code_match.group(1)
79
+ material_desc += f"HSN Code: {hsn_code}\n"
80
+ else:
81
+ material_desc += "HSN Code: Not Found\n"
82
+
83
+ # Extract IGST
84
+ igst_match = re.search(r"IGST\s*:\s*(\d+)\s*%", full_text)
85
+ if igst_match:
86
+ igst = igst_match.group(1)
87
+ material_desc += f"IGST: {igst} %"
88
+ else:
89
+ material_desc += "IGST: Not Found"
90
+
91
+ return material_desc.strip()
92
+
93
+ # Gradio Interface
94
+ def gradio_interface(pdf_file):
95
+ """
96
+ Interface function for Gradio to process the PDF and return the Excel file.
97
+ """
98
+ return extract_data(pdf_file.name)
99
+
100
+ # Define Gradio interface
101
+ interface = gr.Interface(
102
+ fn=gradio_interface,
103
+ inputs=gr.File(label="Upload PDF"),
104
+ outputs=gr.File(label="Download Extracted Excel"),
105
+ title="Dynamic BHEL PO Data Extractor",
106
+ description="Upload a PDF to extract accurate Material Numbers and related data dynamically into an Excel file."
107
+ )
108
+
109
+ if __name__ == "__main__":
110
+ interface.launch()