Updating/saving csv to local machine with user input

I’m making a bike to work tracking tool for my workplace.

I want users to be able to update the spreadsheet through streamlit with km’s biked every week, and hit a save button to save the points in a master spreadsheet.

Something like
if st.button(‘Save your information’):
df.to_csv(‘Bike to Work Spreadsheet’)

I’ve searched the message board extensively, and tried out this:

df = pd.DataFrame({'numbers': [1, 2, 3], 'colors': ['red', 'white', 'blue']})

st.write(df)
if st.button('save dataframe'):
    open('df.csv', 'w').write(df.to_csv())

But no luck. Is this a possibility?

here is one solution for you to download df as a csv:

1 Like

Hi @Mathea, welcome to the Streamlit community!

We showed a similar example here, where you basically are reading and writing to the same file to increment a counter:

That example overwrites the file each time, so that the counter increments. But you could take the same pattern to append to a file, where you write each additional record to the end of the file.

Best,
Randy

Hi Randy,

Thank you for taking the time.

This solution didn’t stick for me. Perhaps I interpreted the solution incorrectly?

if st.button('Save your information'):
    with open("Bike to Work Spreadsheet", "w") as f:
        f.truncate()
        f.write( df.to_csv('Bike to Work Spreadsheet'))

Before I give up hope, would you know if it is possible to have this kind of functionality work when I host the app through a service like Heroku?

Thanks,
M

Hi @Mathea :grinning_face_with_smiling_eyes: You’re on the right track!!

What I’ve done below is first create a text file with the value 0. Then, for every click of the button, I increment the value in the text file by 1. We use this number as the row index of the work spreadsheet that we want to read/write to. With every click of the button, we increment the counter in the progress text file and save the work spreadsheet. Here’s the pseudocode:

import streamlit as st
import pandas as pd

# save annotated results after every button click
def save_results(results_df, button_press, kms_biked, location_visited):
    results_df.at[button_press, 'kms_biked'] = kms_biked
    results_df.at[button_press, 'location_visited'] = location_visited
    results_df.to_csv('bike_to_work.csv', index=None)
    return None

# load spreadsheet with data to be annotated
@st.cache
def load_data():
    # If this is your first run, create an empty csv file with
    # columns kms_biked and location_visited
    df = pd.read_csv('bike_to_work.csv')
    return df


results_df = load_data()

# track which row of results_df to read
with open("progress.txt", "r") as f:
        button_press = f.readline()  # starts as a string
        button_press = 0 if button_press == "" else int(button_press)  # check if its an empty string, otherwise should be able to cast using int()

# enter your biking info for the day
kms_biked = st.number_input("km biked today")
location_visited = st.text_input("Where I biked today")

if st.button("Save your information"):
    button_press += 1
    save_results(results_df, button_press, kms_biked, location_visited)

# track which row of results_df to write to
with open("progress.txt", "w") as f:
        f.truncate()
        f.write(f"{button_press}")

Hope this helps with your biking tracking tool!

Happy Streamlit-ing! :balloon:
Snehan

2 Likes

Would be so much simpler with a little SQLite DB. Don’t you think? :wink:

1 Like

Have you tried this @Mathea ?? I am looking for a better solution as well