This question already has an answer here:
Is there a difference between QFileDialog strings in PyQt4 and PyQt5?
(1 answer)
Closed 1 year ago.
I want to open pdf file through pilihfile pushbutton, then take its name to display on textEdit and display its pdf contents on textEdit_2 by using pymupdf. But i got error said cannot open ('D:/Kuliah/KRIP.pdf', 'PDF Files (*.pdf)'): Invalid argument. I do not know how to fix it.
def pilihfile(self):
files = QFileDialog.getOpenFileName(None, "Open File", "", "PDF Files (*.pdf)")
file_name = str(files))
pdf_document = file_name
self.textEdit.setText(pdf_document)
doc = fitz.open(pdf_document)
hal = doc.pageCount
for i in range (hal):
page = doc.loadPage(i)
page1text = page.get_text().strip()
self.textEdit_2.setPlainText(page1text)
Based on your error message, pdf_document has actually the value of ('D:/Kuliah/KRIP.pdf', 'PDF Files (*.pdf)'). This is because you use QtWidgets.QFileDialog.getOpenFileName with PyQt5 which returns a tuple instead of just a str (check this). If that is the case, try:
files, _ = QFileDialog.getOpenFileName(None, "Open File", "", "PDF Files (*.pdf)")
Related
I used tkpdfviewer to display PDF on a tkinter window (toplevel). After opening a PDF file, the other files are appended behind the previous files. How do I fix this?
file = fd.askopenfilename() # Get the location of the PDF file
if '.pdf' in file:
pdf_viewer = Toplevel(self.root)
pdf_viewer.title(f'{APP_NAME} - {VERSION} [PDF VIEWER]')
pdf_viewer.geometry("650x750")
v1 = pdf.ShowPdf()
pdf_display = v1.pdf_view(pdf_viewer, pdf_location=file)
pdf_display.pack(fill=BOTH, expand=True)
pdf_viewer.mainloop()
I need to make a download button for more than one file. Streamlit's download button doesn't let you download more than one file. I tried to make a few buttons, but the rest just disappear when I click the first one. Is there any way to download two or more files in Streamlit?
I tried this solution from Github, this is what the code looks like:
if st.button("Rozpocznij proces"):
raport2 = Raport.raport_naj_10(gender,year,week,engine)
raportM = raport2[0]
raportO = raport2[1]
st.dataframe(raportM)
st.dataframe(raportO)
zipObj = ZipFile("sample.zip", "w")
# Add multiple files to the zip
zipObj.write("raportM")
zipObj.write("raportO")
# close the Zip File
zipObj.close()
ZipfileDotZip = "sample.zip"
with open(ZipfileDotZip, "rb") as f:
bytes = f.read()
b64 = base64.b64encode(bytes).decode()
href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
Click last model weights\
</a>"
st.sidebar.markdown(href, unsafe_allow_html=True)
But I get this error:
FileNotFoundError: [WinError 2] Nie można odnaleźć określonego pliku: 'raportM'
It says that can't find the file named "raportM".
You are having those errors because the code is written with an assumption that you already have the files stored and you want to generate a zip file for them. zipObj.write("raportM") is looking for the file named "raportM" and there isn't any, because in your case you do not have these files stored. I can see that you are passing variable names as files and that is not going to work.
What you will have to do is to save those variable names as CSV files in your local machine before doing the above operations.
In this case lets modify your code. But before that we need to initialize a session state for the button st.button("Rozpocznij proces") because streamlit button have no callbacks.
processbtn = st.button("Rozpocznij proces")
# Initialized session states
if "processbtn_state" not in st.session_state:
st.session_state.processbtn_state = False
if processbtn or st.session_state.processbtn_state:
st.session_state.processbtn_state = True
raport2 = Raport.raport_naj_10(gender,year,week,engine)
raportM = raport2[0]
raportO = raport2[1]
st.dataframe(raportM)
st.dataframe(raportO)
# Save files
raportM.to_csv('raportM.csv') # You can specify a directory where you want
raportO.to_csv('raportO.csv') # these files to be stored
# Create a zip folder
zipObj = ZipFile("sample.zip", "w")
# Add multiple files to the zip
zipObj.write("raportM.csv")
zipObj.write("raportO.csv")
# close the Zip File
zipObj.close()
ZipfileDotZip = "sample.zip"
with open(ZipfileDotZip, "rb") as f:
bytes = f.read()
b64 = base64.b64encode(bytes).decode()
href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
Click last model weights\
</a>"
st.sidebar.markdown(href, unsafe_allow_html=True)
At this moment, when you pay close attention to your directories you will find 'raportM.csv' and 'raportO.csv' files. You can pass a condition to the download button so that whenever a download is made the files should be deleted in case you don't want to keep them.
Note: You may encounter fileNotFound Error but does not mean that it won't work, you will just need to know where you are saving the files.
How can I change my code so I can save my final pdf (MergedFiles.pdf) with a name chosen by the user and in a location chosen by them. I would like to have a popup(maybe tkinter?) that will give the user the option of choosing the name and location to save the pdf file.
import PyPDF2
# Open the files that have to be merged one by one
pdf1File = open(filepath, 'rb')
pdf2File = open('Summary_output.pdf', 'rb')
# Read the files that you have opened
pdf1Reader = PyPDF2.PdfFileReader(pdf1File)
pdf2Reader = PyPDF2.PdfFileReader(pdf2File)
# Create a new PdfFileWriter object which represents a blank PDF document
pdfWriter = PyPDF2.PdfFileWriter()
# Loop through all the pagenumbers for the first document
for pageNum in range(pdf1Reader.numPages):
pageObj = pdf1Reader.getPage(pageNum)
pdfWriter.addPage(pageObj)
# Loop through all the pagenumbers for the second document
for pageNum in range(pdf2Reader.numPages):
pageObj = pdf2Reader.getPage(pageNum)
pdfWriter.addPage(pageObj)
# Now that you have copied all the pages in both the documents, write them into the a new document
pdfOutputFile = open('MergedFiles.pdf', 'wb')
pdfWriter.write(pdfOutputFile)
# Close all the files - Created as well as opened
pdfOutputFile.close()
pdf1File.close()
pdf2File.close()
You can do this with a tkinter filedialog.
root = tk.Tk()
root.withdraw()
pdfPath = filedialog.asksaveasfilename(defaultextension = "*.pdf", filetypes = (("PDF Files", "*.pdf"),))
if pdfPath: #If the user didn't close the dialog window
pdfOutputFile = open(pdfPath, 'wb')
pdfWriter.write(pdfOutputFile)
pdfOutputFile.close()
pdf1File.close()
pdf2File.close()
Firstly, it creates and hides a tkinter window. If you didn't do this an empty window would come up when you launched the file dialog. Then it uses filedialog.asksaveasfilename to launch the native OS file dialog. I've specified that it should ask for PDF files only. Then the if statement checks if a path has been returned, if it has it follows the same process as before.
I'm a new user of Qt and I'm trying to fix a persistent crashing issue that happens in my 'open file' dialogue. Whenever I open a file dialogue to select a file and decide to hit cancel instead, it causes python to stop working.
This is what the code looks like right now:
# get save file
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
self.matlocation = savefile
I've tried using:
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
if(!fileName.isEmpty()&& !fileName.isNull()){
self.matlocation = savefile
}
but this is still causing crashes. Am I missing something?
Thanks in advance.
Edit
It's part of a larger function:
So it's part of a function from a larger .py. The function as it stands starts by loading in a mat file:
def loadmat(self):
from PyQt5 import QtWidgets
import functions.plotting as plot
# get save file
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
self.matlocation = savefile
# set mat location in GUI box
self.gui.samplelocBox.setPlainText(self.matlocation)
I'm trying to make a savefile dialog in tkinter. I need to save the file name to use later. However, I do not want the filedialog to accept selecting an already existing file name.
So far I only have this:
from tkinter import filedialog
my_file = filedialog.asksaveasfilename(defaultextension = ".myfile",
filetypes = [("MY SUPER FILE", ".myfile"),
("All files", ".*")])
One possibility would be to get the file name, check if it exists (using os.path.isfile) and ask again the user for new name if there is already a file with the same name. However, the tkinter filedialog asks the user "file already exists. do you want to overwrite?". So it seems confusing if later I tell the user that I do not accept the filename choice. Is there a way to force the tkinter filedialog to not ask the user about the overwriting?
Edit: Based on the suggestions in the answers, I tried to make my own save file dialog.
I basically only added a warning to the tkinter save dialog:
class MySaveFileDialog(filedialog.FileDialog):
""" File save dialog that does not allow overwriting of existing file"""
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
messagebox.showarning("The current file name already exists. Please give another name to save your file.")
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
So, it looks pretty simple. Then I thought: I need to create my own asksaveasfilename function.
I went to check the source:
def asksaveasfilename(**options):
"Ask for a filename to save as"
return SaveAs(**options).show()
Humm.. I need to see what is SaveAs doing.
class SaveAs(_Dialog):
"Ask for a filename to save as"
command = "tk_getSaveFile"
Aaannddd... i'm lost. I don't understand how this pieces fit together. 'SaveAs' just has the command tk_getSaveFile. How is the SaveFileDialog being used here? And how can I make my own myasksaveasfilename function?
There is no such option. If you want to get rid of the security question, then you'll have to write your own file dialog.
If you look at filedialog.py, you'll see that the dialog is implemented in Python. So all you have to do is to extend the class SaveFileDialog and override the method ok_command() with one that doesn't allow to select an existing file name.
You can use most of the existing code and just change a few texts to achieve your goal.
I haven't tested it but this code should work:
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
d = Dialog(self.top,
title="Overwrite Existing File",
text="You can't overwrite an existing file %r. Please select a new name." % (file,),
bitmap='error',
default=0,
strings=("OK",))
return
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
An answer to a slightly adjacent topic, but this was the closest existing question on SO so assume others may end up here when faced with the same problem, and I got my answer from above information.
If you are looking to select a tk.filedialog.asksaveasfile, but without overwriting an existing file (ie append to it), and wanting to avoid users being faced with the 'Do you want to overwrite?' popup, one can select the append mode, and turn off the overwrite popup.
outfilename = tk.filedialog.asksaveasfile(title = 'Save processing output CSV',
initialdir = output_directory,
defaultextension = '.csv',
mode = 'a',
confirmoverwrite = False,
filetypes = (('csv File', '.csv'),)
)
To complete what Aaron said, here is the current code of ok_command:
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
d = Dialog(self.top,
title="Overwrite Existing File Question",
text="Overwrite existing file %r?" % (file,),
bitmap='questhead',
default=1,
strings=("Yes", "Cancel"))
if d.num != 0:
return
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
You can achieve this using tkFileDialog.asksaveasfilename(confirmoverwrite=False)
Here is a mock up:
import tkFileDialog
import tkMessageBox as mbox
class Example():
proceed = False
while proceed == False:
dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False)
fname = dlg
if fname != '':
try:
f = open(fname, "r")
f.close()
mbox.showerror("Error","File exists - Choose another file name")
except:
mbox.showinfo("Info","File does not exist - Continue")
proceed = True
else:
break
print("Finished")