Write multiple rows to a CSV - python

I have a small GUI which should write the values ​​into a CSV file. However, the header is always written instead of just the new entries.
this is how it looks in the csv:
Amount, Time
1000,12:13:40
Amount, Time
2000,12:14:30
What I want:
Amount, Time
1000,12:13:40
2000,12:14:30
def submit():
import csv
import datetime
with open("Data_amount.csv", "a", newline="") as csvfile:
writer = csv.writer(csvfile)
#Header
writer.writerow(["Amount", "Time"])
#Input
input_amount = entry_listbox.get()
#Time
now = datetime.datetime.now()
now_str = now.time().strftime("%H:%M:%S")
writer.writerow([input_amount, now_str])
timestamp = datetime.datetime.now()
input_amount2 = entry_listbox.get()
if input_amount2 != "":
listbox_stuekzahlen.insert(tkinter.END, f'{timestamp:%H:%M:%S} - {input_amount2} Stk.')
entry_listbox.delete(0,tkinter.END)
else:
tkinter.messagebox.showwarning(title="Warning!", message="INPUT!")

You unconditionally write the header again each time you call submit. Either:
Remove that header write, and have, somewhere outside submit (early in your program, run exactly once), the code that initializes (opens in "w" mode so the file is cleared) the file with just the header, so each submit doesn't add an extra copy, or
Leave the header write in, but make it conditional on the file being empty (so you only write it when the file is already empty, and otherwise assume the file already has the header), e.g.
with open("Data_amount.csv", "a", newline="") as csvfile:
writer = csv.writer(csvfile)
#Header
if not os.fstat(csvfile.fileno()).st_size:
writer.writerow(["Amount", "Time"]) # Write header only if input is empty

Related

How do I automate the repetitive action of applying filters in CSV in Python?

In a nutshell what I want is to be able to:
select a file thats csv,or anything excel
From that file
apply a filter on the the selections needed
save that applied filter view to a new file xls that just adds "for review" to the file name to the current folder
`
# Import the necessary libraries
import openpyxl
import os
import time
import csv
# Define the path to the CSV file
csv_file = "C:/Users/USERNAME//Desktop/filename.csv"
# Open the CSV file and create a reader object
with open(csv_file, "r") as f:
reader = csv.reader(f)
# Iterate over the rows in the reader
rows = []
for row in reader:
rows.append(row)
# Open the Excel document and create a new worksheet
wb = openpyxl.Workbook()
ws = wb.active
# Write the rows from the CSV file to the Excel worksheet
for row in rows:
ws.append(row)
# Apply filters to the top row
ws.auto_filter.ref = "A1:Z1"
# Filter column A by "Network Upload Egress" and "Removable Media Egress"
ws.auto_filter.add_filter_column(0, \["Network Upload Egress", "Removable Media Egress"\])
# Save a copy of the Excel document with "Evidence Review" added to the file name
new_file = os.path.splitext(excel_file)\[0\] + " Evidence Review.xlsx"
# Display a loading animation while the process is running
print("Processing...")
for i in range(10):
time.sleep(0.5)
print(".", end="")
# Save the copy of the Excel document
try:
wb.save(new_file)
print("\\nProcess complete!")
except IOError:
print("Error saving the copy of the Excel document. Make sure you have permission to save files to the specified location.")`
try the below code.
import csv
def filter_csv(input_file, output_file, filter_column, filter_value):
with open(input_file, 'r') as in_file, open(output_file, 'w', newline='') as out_file:
# Create CSV reader and writer
reader = csv.reader(in_file)
writer = csv.writer(out_file)
# Find the index of the filter column
header = next(reader)
filter_column_index = header.index(filter_column)
# Write the header row to the output file
writer.writerow(header)
# Iterate through the rows in the input file
for row in reader:
# If the filter value is in the filter column, write the row to the output file
if row[filter_column_index] == filter_value:
writer.writerow(row)
Example usage
filter_csv('input.csv', 'output.csv', 'State', 'CA')

header in csv file printing every other line

I've been working this problem way too long, please explain to me why the header keeps repeating in my output csv.
I have an input csv with this data:
name,house
"Abbott, Hannah",Hufflepuff
"Bell, Katie",Gryffindor
"Bones, Susan",Hufflepuff
"Boot, Terry",Ravenclaw
The problem requires reversing last and first name, separate name into two columns, and make a new header with 3 columns for the output csv. Here's what I have:
while True:
try:
# open file
with open(sys.argv[1]) as file:
# make reader
reader = csv.reader(file)
# skip first line (header row)
next(reader)
# for each row
for row in reader:
# identify name
name = row[0]
# split at ,
name = name.split(", ")
# create var last and first, identify var house
last = name[0]
first = name[1]
house = row[1]
# writing the new csv
with open(sys.argv[2], "a") as after:
writer = csv.DictWriter(after, fieldnames=["first", "last", "house"])
# HEADER ONLY NEEDS TO OCCUR ONCE
writer.writeheader()
writer.writerow({"first": first, "last": last, "house": house})
sys.exit(0)
my output csv:
first,last,house
Hannah,Abbott,Hufflepuff
first,last,house
Katie,Bell,Gryffindor
first,last,house
Susan,Bones,Hufflepuff
I've tried removing the while loop, unindenting and indenting, writing a row manually with the header names (which caused errors). Please help. Thanks!
You can add a variable that hold whether a header was printed or not, ex write_header
while True:
try:
write_header = True
# open file
with open(sys.argv[1]) as file:
# make reader
reader = csv.reader(file)
# skip first line (header row)
next(reader)
# for each row
for row in reader:
# identify name
name = row[0]
# split at ,
name = name.split(", ")
# create var last and first, identify var house
last = name[0]
first = name[1]
house = row[1]
# writing the new csv
with open(sys.argv[2], "a") as after:
writer = csv.DictWriter(after, fieldnames=["first", "last", "house"])
# HEADER ONLY NEEDS TO OCCUR ONCE
if write_header:
writer.writeheader()
write_header = False
writer.writerow({"first": first, "last": last, "house": house})
sys.exit(0)
See how i used write_header
On an other note, you can refactor your code to open the csv writer before the for loop, write headers there, then write values as you do now without the need to reopen the file each time you want to write a row

How to remove specifc row from csv file using python

I am working on one program and trying to achieve following functionalities.
add new student
Remove student based on id
here is my code
from csv import writer
import csv
def add(file_name, list_of_elem):
# Open file in append mode
with open(file_name, 'a+', newline='') as write_obj:
# Create a writer object from csv module
csv_writer = writer(write_obj)
# Add contents of list as last row in the csv file
csv_writer.writerow(list_of_elem)
def remove():
id = input("Enter ID : ")
with open('students.csv', 'rb') as inp, open('students.csv', 'wb') as out:
writer = csv.writer(out)
for row in csv.reader(inp):
if row[0] != id:
writer.writerow(row)
# List of strings
row_contents = [11,'mayur','Java','Tokyo','Morning']
# Append a list as new line to an old csv file
add('students.csv', row_contents)
remove()
add function works properly but when i tried remove function it removes all existing entries.Could anyone please help me.
First I will show the code and below I will left some comments about the changes.
from csv import writer
import csv
def add(file_name, list_of_elem):
# Open file in append mode
with open(file_name, 'a+', newline = '') as write_obj:
# Create a writer object from csv module
csv_writer = writer(write_obj)
# Add contents of list as last row in the csv file
csv_writer.writerow(list_of_elem)
def remove():
idt = input("Enter ID : ")
with open('students.csv', 'r') as inp:
newrows = []
data = csv.reader(inp)
for row in data:
if row[0] != idt:
newrows.append(row)
with open('students.csv', 'w') as out:
csv_writer = writer(out)
for row in newrows:
csv_writer.writerow(row)
def display():
with open('students.csv','r') as f:
data = csv.reader(f)
for row in data:
print(row)
# List of strings
row_contents = [10,'mayur','Java','Tokyo','Morning']
add('students.csv', row_contents)
row_contents = [11,'mayur','Java','Tokyo','Morning']
add('students.csv', row_contents)
row_contents = [12,'mayur','Java','Tokyo','Morning']
add('students.csv', row_contents)
# Append a list as new line to an old csv file
display()
remove()
If your file is a CSV, you should use a text file, instead of a binary one.
I changed the name of the variable id to ìdt because id is built-in to return the identity of an object and it's not a good practice overwrite built-in functions.
To remove only rows with an specific idt you should read all the file, store into a var (list), remove what you want to delete and only after that save the result.
You should use a temporary file instead of opening and writing to the same file simultaneously. Checkout this answer: https://stackoverflow.com/a/17646958/14039323

How to write a new line in same .csv file each time script is ran?

I have the below script to write to a .csv file - which works, but I am running the script on multiple files..
I am using the: from csv import DictWriter
Currently it just write and updates the same line over and over again.. So my /metrics.csv only ever gets one row... How could I get this to update to a new row each time?
/find_pending_records.py
def get_excel_data(self):
"""Places excel data into pandas dataframe"""
...........
with open("./logs/metrics.csv", "w", newline="") as f:
csv_writer = DictWriter(f, ['date', 'total', 'processed', 'skipped', 'total_zips', 'success_rate'])
csv_writer.writeheader()
currentDT = datetime.datetime.now()
success_rate = num_valid_records / total_records * 100
csv_writer.writerow(dict(date=currentDT,
total=total_records,
processed=num_valid_records,
skipped=num_invalid_records,
success_rate=num_valid_records / total_records * 100))
return self.clean_data_frame(excel_data)
Without even going too deep in to your code the problem is the following line
with open("./logs/metrics.csv", "w", newline="") as f:
That opens the file in write mode so you need to change the w to a so it opens the file in append mode instead.

Add data to new column and first row in CSV file

I have a python function that creates a CSV file using a Postgresql copy statement. I need to add a new column to this spreadsheet called 'UAL' with an example value in the first row of say 30,000, but without editing the copy statement. This is the current code:
copy_sql = 'COPY (
SELECT
e.name AS "Employee Name",
e.title AS "Job Title"
e.gross AS "Total Pay",
e.total AS "Total Pay & Benefits",
e.year AS "Year",
e.notes AS "Notes",
j.name AS "Agency",
e.status AS "Status"
FROM employee_employee e
INNER JOIN jurisdiction_jurisdiction j on e.jurisdiction_id = j.id
WHERE
e.year = 2011 AND
j.id = 4479
ORDER BY "Agency" ASC, "Total Pay & Benefits" DESC
)'
with open(path, 'w') as csvfile:
self.cursor.copy_expert(copy_sql, csvfile)
What I am trying to do is use something like csv.writer to add content like this:
with open(path, 'w') as csvfile:
self.cursor.copy_expert(copy_sql, csvfile)
writer = csv.writer(csvfile)
writer.writerow('test123')
But this is adding the text to the last row. I am also unsure how to add a new header column. Any advice?
adding a header is easy: write the header before the call to copy_expert.
with open(path, 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["my","super","header"])
self.cursor.copy_expert(copy_sql, csvfile)
But adding a column cannot be done without re-reading the file again and add your info on each row, so the above solution doesn't help much.
If the file isn't too big and fits in memory, you could write the sql output to a "fake" file:
import io
fakefile = io.StringIO()
self.cursor.copy_expert(copy_sql, fakefile)
now rewind the file and parse it as csv, add the extra column when writing it back
import csv
fakefile.seek(0)
with open(path, 'w', newline="") as csvfile:
writer = csv.writer(csvfile)
reader = csv.reader(fakefile) # works if copy_expert uses "," as separator, else change it
writer.writerow(["my","super","header","UAL"])
for row in reader:
writer.writerow(row+[30000])
or instead of the inner loop:
writer.writerows(row+[30000] for row in reader)
And if the file is too big, write it in a temp file, and proceed the same way (less performant)

Categories