Now that the data in the text area from our previous lesson has changed, we'd want to save it. There are two ways we can save in Python: one is by displaying the Save As dialog box so that a user can save the file under a different name, or we can just get on and save the file without any dialog boxes popping up. Our menu has those two options, Save and Save As. We'll implement the Save option first.
Saving a file is fairly straightforward in Python: get the text you want to save, get the name of the file you want to save, use the open function with a write parameter. To get the text to save, you need to use the get function of the Text widget:
textAreaText = textArea.get('1.0', 'end-1c')
This gets the text from our Text widget, the one called textArea. We're then transferring this text to another variable, one we've called textAreaText. But notice what's in between the round brackets of get:
'1.0', 'end-1c'
The '1.0' at the start means grab the text from line one, characters zero. This is right at the beginning of the text area. We need to go right to the end of the text area. We could just use tk.END here. But the Text widget puts a new line character at the end of your text. To get rid of this newline character, you can use 'end-1c'. This means the end of the text minus one character.
To tell Python that you want to create a file object that has write capabilities, you can do this:
save_text = open(filename, 'w')
Between the round brackets of open, we have the file name and path and then the mode, which is 'w'. Our file object is then placed in the variable called save_text.
To actually write the file you need the write function:
save_text.write(textAreaText)
In between the round brackets of write you need the text that you want to write to your file.
Finally, you can close the file object:
save_text.close()
So the full code would be this:
text_area_text = textArea.get('1.0', 'end-1c')
save_text = open(filename, 'w')
save_text.write(text_area_text)
save_text.close()
However, there is a problem with this code: how do we get the file name? Where is it coming from? When we opened a file, we did so from the openfile function. A file path was placed into a variable called filename. We got this from the open file dialog box:
def openfile():
filename = filedialog.askopenfilename(initialdir="/",
title="Open File",
filetypes=(("Text Files", "*.txt"), ("All Files", "*.*")))
The problem we have is that filename is local to the openfile function. It can't be seen from outside of this function. But we want a separate function called savefile:
def savefile():
text_area_text = textArea.get('1.0', 'end-1c')
save_text = open(filename, 'w')
save_text.write(text_area_text)
save_text.close()
The highlighted filename in the savefile function above wouldn't work. It won't work because this filename variable knows nothing about the other filename variable from the openfile function.
One solution we can implement is to set up something called a global variable. Making a variable global means it can be accessed from anywhere in your code file. Try it out. Add a filename variable right at the top of your code:
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
filename = ''
Because the filename variable is outside of the functions, it has the potential to be global.
As the first line of your openfile function, set up filename to point to this global variable:
def openfile():
global filename
#REST OF OUR CODE HERE
So you only need the keyword global before the variable name. This is enough to make sure that this filename variable is accessing the filename variable we set up at the top of the code. If we missed the global keyword out, filename would only be local to the openfile function. We wouldn't be able to see it from the savefile function we're about to set up.
Now set up a new function. Call it savefile. Here's the code for it:
def savefile():
global filename
if filename:
text_area_text = textArea.get('1.0', 'end-1c')
save_text = open(filename, 'w')
save_text.write(text_area_text)
save_text.close()
else:
messagebox.showinfo("Error", "No file open")
Your code in PyCharm should look like this
The if statement is testing to see if there is something in the filename. If not, then we can display a message box. (We should wrap this in a try except block as well, just in case something else goes wrong. We'll leave that out, though.)
So, what's happening is that a user clicks File > Open and searches for a file. When this file is opened, its name and path go into the filename variable. This filename variable is made global. Because it's global, the savefile function can now see it.
Before you can try it out, locate the code that sets up your menu system. Change this line:
fileMenuItems.add_command(label="Save", command=openfile)
to this:
fileMenuItems.add_command(label="Save", command=savefile)
In other words, point your Save menu at your new savefile function.
One other thing to do before trying it out. Create a backup copy of your postcodes file. Copy and paste it to a different folder. That way, you can try it again and not lose the original.
You can try your program out now. Before opening a file, click File > Save. You should see your message box display:
Now open the postcodes file. The changed version of the postcodes will display in the text area. Click File > Save to save this changed version. If you examine the postcodes file outside of your program, in an Explorer or Finder window, you'll see the new version has been saved.
In the next lesson, we'll take a look at Save As rather than just Save.