我正在尝试从电子表格获取地址.. 将这些地址转换为纬度和经度.. 然后将标记添加到 TkinterMapView 地图上的这些坐标。
我使用openpyxl制作了一个工作簿:
wB = load_workbook('HoldingCats(1).xlsx')
wS = wB.active
column_b = wS['B']
循环浏览工作簿并打印出地址。将“B 列”中的单元格设置为函数 AddressCellB:
column_b = wS['B']
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
一切正常并打印出地址......
但是当我尝试在 .geocode() 中运行函数 AddressCellB 来获取 .address、.latitude 和 .longitude...
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB, timeout=None)
contactName = getLoc.address
lat1 = getLoc.latitude
long1 = getLoc.longitude
Marker1 = MAP.set_marker( lat1, long1, contactName)
我收到错误:
lat1 = getLoc.latitude
^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'address'
我这样做很奇怪吗?
为什么 AddressCellB 函数不会从 .geocode() 返回 .address、.latitude、.longitude?
是否有更好的方法从电子表格中提取地址列表,将地址隐藏到坐标,并为每个地址建立一个标记(在 tkintermapview 中)?
追溯:
Traceback (most recent call last): File "/Users/jawn/Desktop/EXcel/Excel2Me.py", line 377, in <module>
contactName = getLoc.address
^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'address'
讨论的代码:
wB = load_workbook('HoldingCats(1).xlsx')
wS = wB.active
column_b = wS['B']
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB, timeout=None)
contactName = getLoc.address
lat1 = getLoc.latitude
long1 = getLoc.longitude
Marker1 = MAP.set_marker( lat1, long1, contactName)
完整代码:
import customtkinter as ctk
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkintermapview import TkinterMapView
from PIL import Image, ImageTk
from CTkSpinbox import *
import openpyxl
from openpyxl.workbook import Workbook
from openpyxl import load_workbook
from geopy.geocoders import Nominatim
import googlemaps
from datetime import datetime
WholeApp = ctk.CTk()
WholeApp.title("Locations!")
WholeApp.geometry("1400x900")
# DEF ##############################################
def slide(e):
MAP.set_zoom(Map_Slider.get())
def mutton():
MAP.set_address(mapEntry.get())
def theme_stuff():
pass
def load_SetData():
path = "LocationsMM.xlsx"
workbook = openpyxl.load_workbook(path)
sheet = workbook.active
list_values = list(sheet.values)
for col_name in list_values[0]:
SetTreeView.heading("#1", text="Set")
SetTreeView.heading("#2", text="Business")
SetTreeView.heading("#3", text="Address")
SetTreeView.heading("#4", text="Shoot Date")
SetTreeView.heading("#5", text="BG Count")
SetTreeView.heading("#6", text="Notes")
#SetTreeView.heading(col_name, text=col_name)
for value_tuple in list_values[1:]:
SetTreeView.insert('', tk.END, values=value_tuple)
def load_HolCatData():
path2 = "HoldingCats(1).xlsx"
workbook2 = openpyxl.load_workbook(path2)
sheet2 = workbook2.active
list_values2 = list(sheet2.values)
for col_name2 in list_values2[0]:
HolCatTreeView.heading("#1", text ="Name")
HolCatTreeView.heading("#2", text ="Address")
HolCatTreeView.heading("#3", text ="Contact")
HolCatTreeView.heading("#4", text ="SQFT")
HolCatTreeView.heading("#5", text ="$$$")
for value_tuple2 in list_values2[1:]:
HolCatTreeView.insert('',tk.END, values = value_tuple2)
def calc():
calcRoot = ctk.CTk()
calcRoot.title("Something Doesnt Add Up")
calcEntry = ctk.CTkEntry(calcRoot, width=150, height=50)
calcEntry.grid(row=0, column=0, pady=5, padx=5, columnspan=3)
button_1 = ctk.CTkButton(calcRoot, text="1", corner_radius=50 ,width=30, height=30)
button_1.grid(row=1, column=0, pady=3, padx=3)
button_2 = ctk.CTkButton(calcRoot, text="2", corner_radius=50 ,width=30, height=30)
button_2.grid(row=1, column=1, pady=3, padx=3)
button_3 = ctk.CTkButton(calcRoot, text="3", corner_radius=50 ,width=30, height=30)
button_3.grid(row=1, column=2, pady=3, padx=3)
button_4 = ctk.CTkButton(calcRoot, text="4", corner_radius=50 ,width=30, height=30)
button_4.grid(row=2, column=0, pady=3, padx=3)
button_5 = ctk.CTkButton(calcRoot, text="5", corner_radius=50 ,width=30, height=30)
button_5.grid(row=2, column=1, pady=3, padx=3)
button_6 = ctk.CTkButton(calcRoot, text="6", corner_radius=50 ,width=30, height=30)
button_6.grid(row=2, column=2, pady=3, padx=3)
button_7 = ctk.CTkButton(calcRoot, text="7", corner_radius=50 ,width=30, height=30)
button_7.grid(row=3, column=0, pady=3, padx=3)
button_8 = ctk.CTkButton(calcRoot, text="8", corner_radius=50 ,width=30, height=30)
button_8.grid(row=3, column=1, pady=3, padx=3)
button_9 = ctk.CTkButton(calcRoot, text="9", corner_radius=50 ,width=30, height=30)
button_9.grid(row=3, column=2, pady=3, padx=3)
button_E = ctk.CTkButton(calcRoot, text="=", corner_radius=50 ,width=30, height=30)
button_E.grid(row=4, column=0, pady=3, padx=3)
button_0 = ctk.CTkButton(calcRoot, text="0", corner_radius=50 ,width=30, height=30)
button_0.grid(row=4, column=1, pady=3, padx=3)
button_S = ctk.CTkButton(calcRoot, text="-", corner_radius=50 ,width=30, height=30)
button_S.grid(row=4, column=2, pady=3, padx=3)
# LABEL #
LocationsLabel = ctk.CTkLabel(WholeApp,
text="Locations!",
font=("cochin", 55),
text_color="white",
)
LocationsLabel.grid(row=0, column=1, pady=2, padx=2)
# THEME COMBO #
theme_change = ctk.CTkComboBox(WholeApp, values=["Dark", "Light", "Sports", "Elmo"], command=theme_stuff)
theme_change.grid(row=0, column=0, pady=5, padx=5)
# Excel Combo #
def ExcelFileChoice():
pass
excel_combo = ctk.CTkComboBox(WholeApp, values = ["Set", "HolCat"], command=ExcelFileChoice)
excel_combo.grid(row=0, column=2, pady=2, padx=2)
# TAB FRAME1 ##############################################
# SEARCH TAB #
TabFrame1=ctk.CTkTabview(WholeApp,
width=55,
height=300,
corner_radius=10,
border_width=1,
segmented_button_selected_color="teal",
segmented_button_selected_hover_color="gray",
text_color="black"
)
TabFrame1.grid(row=1, column=0, pady=5, padx=(50,1))
Tab_search = TabFrame1.add("Search")
SetSearch = ctk.CTkEntry(Tab_search,
width=185,
placeholder_text="set",
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
SetSearch.insert(0, "Set")
SetSearch.bind("<FocusIn>", lambda e: SetSearch.delete('0', 'end'))
SetSearch.grid(row=0, column=0, columnspan=2, pady=3, padx=5)
BusinessSearch = ctk.CTkEntry(Tab_search,
width=185,
placeholder_text=("Address"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
BusinessSearch.insert(0, "Business")
BusinessSearch.bind("<FocusIn>", lambda e: BusinessSearch.delete('0', 'end'))
BusinessSearch.grid(row=1, column=0, columnspan=2, pady=3, padx=5)
AddressSearch = ctk.CTkEntry(Tab_search,
width=185,
placeholder_text=("Shoot Date"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
AddressSearch.insert(0, "Address")
AddressSearch.bind('<FocusIn>', lambda e: AddressSearch.delete('0', 'end'))
AddressSearch.grid(row=2, column=0, columnspan=2, pady=3, padx=5)
ShootDateSearch = ctk.CTkEntry(Tab_search,
width=185,
placeholder_text=("Shoot Date"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
ShootDateSearch.insert(0, "Shoot Date")
ShootDateSearch.bind('<FocusIn>', lambda e: ShootDateSearch.delete('0', 'end'))
ShootDateSearch.grid(row=3, column=0, columnspan=2, pady=3, padx=5)
bg_label = ctk.CTkLabel(Tab_search, text=" BG",
font=("cochin", 15),
text_color="white",
)
bg_label.grid(row=4, column=0)
def print_label(count):
print(count)
spin_var = ctk.IntVar()
BGSearch = CTkSpinbox(Tab_search,
font=("cochin", 15),
start_value=50,
min_value=0,
max_value=500,
variable=spin_var,
command=print_label
)
BGSearch.grid(row=4, column=1, pady=3, padx=5)
NotesSearch = ctk.CTkEntry(Tab_search,
width=185,
placeholder_text=("Notes"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
NotesSearch.grid(row=5, column=0, columnspan=2, pady=3, padx=5)
SearchButton = ctk.CTkButton(Tab_search,
font=("cochin",18),
text="Search",
text_color="black",
fg_color="teal",
corner_radius=10,
width=100,
hover_color="black"
)
SearchButton.grid(row=6, column=0, columnspan=2, pady=(5,5), padx=5)
##############################################################
# ADD TAB #
Tab_Add = TabFrame1.add("Add")
SetAdd = ctk.CTkEntry(Tab_Add,
width=185,
placeholder_text=("Set"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
SetAdd.grid(row=0, column=0, pady=3, padx=5)
SetAdd.insert(0, "Set")
SetAdd.bind("<FocusIn>", lambda e: SetAdd.delete('0', 'end'))
AddressAdd = ctk.CTkEntry(Tab_Add,
width=185,
placeholder_text=("Address"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
AddressAdd.grid(row=1, column=0, pady=3, padx=5)
ShootDateAdd = ctk.CTkEntry(Tab_Add,
width=185,
placeholder_text=("Shoot Date"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
ShootDateAdd.grid(row=2, column=0, pady=3, padx=5)
def print_label1(count1):
print(count1)
spin_var1 = ctk.IntVar()
BGAdd = CTkSpinbox(Tab_Add,
start_value=50,
min_value=0,
max_value=500,
variable=spin_var1,
command=print_label1,
font=('cochin', 15),
)
BGAdd.grid(row=3, column=0, pady=3, padx=5)
NotesAdd = ctk.CTkEntry(Tab_Add,
width=185,
placeholder_text=("Notes"),
font=('cochin', 15),
corner_radius=10,
border_width=1,
)
NotesAdd.grid(row=4, column=0, pady=3, padx=5)
AddButton = ctk.CTkButton(Tab_Add,
font=("cochin",18),
text="Search",
text_color="black",
fg_color="teal",
corner_radius=10,
width=100,
hover_color="black"
)
AddButton.grid(row=5, column=0, pady=(5,5), padx=5)
###################################################
# TOOLS TAB ######################
Tab_Tools = TabFrame1.add("Tools")
ButtonCalc = ctk.CTkButton(Tab_Tools,
font=("cochin",15),
text="Calc",
fg_color="teal",
corner_radius=10,
border_color="black",
border_width=1,
hover_color="black",
command=calc
)
ButtonCalc.grid(row=0, column=0, pady=5, padx=5)
###################################################
# EXCEL TAB FRAME ###############################################
treeFrame=ctk.CTkTabview(WholeApp,
width=800,
height=300,
corner_radius=10,
border_width=1,
)
treeFrame.grid(row=1, column=1, pady=1, padx=1, columnspan=3)
# SET TAB #
SetTab = treeFrame.add("Set")
SetScroll = ctk.CTkScrollbar(SetTab,
button_color="teal",
fg_color="black"
)
SetScroll.pack(side="right", fill="y")
cols = ("SET", "BUSINESS", "ADDRESS", "SHOOT DATE", "BG COUNT", "NOTES")
SetTreeView = ttk.Treeview(SetScroll,
yscrollcommand=SetScroll.set,
columns=cols,
height=12
)
SetTreeView['show'] = 'headings'
SetTreeView.column("SET", width=175)
SetTreeView.column("BUSINESS", width=250)
SetTreeView.column("ADDRESS", width=250)
SetTreeView.column("SHOOT DATE", width=150)
SetTreeView.column("BG COUNT", width=50)
SetTreeView.column("NOTES", width=100)
SetTreeView.pack()
SetScroll.configure(command=SetTreeView.yview)
load_SetData()
# HolCat #
HolCatTab = treeFrame.add("Holcat")
HolCatScroll = ctk.CTkScrollbar(HolCatTab,
button_color="teal",
fg_color="black"
)
HolCatScroll.pack(side="right", fill="y")
cols2 = ("NAME", "ADDRESS", "CONTACT", "SQFT", "$")
HolCatTreeView = ttk.Treeview(HolCatScroll,
yscrollcommand=HolCatScroll.set,
columns=cols2,
height=12
)
HolCatTreeView["show"] = 'headings'
HolCatTreeView.column("ADDRESS", width=250)
HolCatTreeView.column("CONTACT", width=275)
HolCatTreeView.column("SQFT", width=100)
HolCatTreeView.column("$", width=150)
HolCatTreeView.pack()
HolCatScroll.configure(command=HolCatTreeView.yview)
load_HolCatData()
# MAP_FRAME ######################
mapEntryFrame=ctk.CTkTabview(WholeApp,
width=800,
height=200,
corner_radius=10,
border_width=1,
text_color="black",
segmented_button_selected_color="teal",
segmented_button_selected_hover_color="gray"
)
mapEntryFrame.grid(row=2, column=0, pady=1, padx=(50,5), columnspan=3, sticky="nsew")
TabMap = mapEntryFrame.add("Map")
mapEntry = ctk.CTkEntry(TabMap,
width=200,
placeholder_text="Address",
font=("cochin", 13),
corner_radius=10,
)
mapEntry.grid(row=0, column=1, pady=1, padx=5, sticky="nsew")
mapButton = ctk.CTkButton(TabMap,
text="Search",
fg_color="teal",
font=("cochin", 13),
text_color="black",
corner_radius=10,
command=mutton,
width=100,
hover_color="black"
)
mapButton.grid(row=0, column=0, pady=1, padx=1)
MAP = TkinterMapView(TabMap,
width=750,
height=300,
corner_radius=15
)
MAP.grid(row=1, column=1, pady=5, padx=5, columnspan=2)
MAP.set_address("Manhattan")
MAP.set_zoom(12)
wB = load_workbook('HoldingCats(1).xlsx')
wS = wB.active
column_b = wS['B']
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB)
contactName = getLoc.address
lat1 = getLoc.latitude
long1 = getLoc.longitude
Marker1 = MAP.set_marker( lat1, long1, contactName)
Map_Slider = ctk.CTkSlider(TabMap,
from_=4,
to=20,
orientation=tk.VERTICAL,
command=slide,
button_color="teal",
fg_color="black",
progress_color="black",
button_hover_color="black"
)
Map_Slider.grid(row=1, column=0, pady=5, padx=5)
TabEntry = mapEntryFrame.add("Entry")
ButtonEntry = ctk.CTkButton(TabEntry,
width=100,
text="Note",
font=("cochin", 15),
text_color="black",
fg_color="teal",
corner_radius=10,
hover_color="black"
)
ButtonEntry.grid(row=0, column=0, pady=5, padx=5)
TextBoxFrame = ctk.CTkTextbox(TabEntry,
width=600,
height=200,
border_width=1,
corner_radius=15,
)
TextBoxFrame.grid(row=0, column=1, pady=10, padx=10)
WholeApp.mainloop()
更新编辑:在 for 循环中添加了标记和地理函数。尝试让循环在每个循环中添加一个新的标记。 我仍然收到错误:“NoneType”对象没有属性“地址”。
MAP = TkinterMapView(TabMap,
width=750,
height=300,
corner_radius=15
)
MAP.grid(row=1, column=1, pady=5, padx=5, columnspan=2)
MAP.set_address("Manhattan")
MAP.set_zoom(12)
wB = load_workbook('HoldingCats(2).xlsx')
wS = wB.active
column_b = wS['B']
#for cell in column_b:
# AddressCellB = cell.value
for i, cell in enumerate(column_b, start=1):
AddressCellB2 = i, cell.value
print(AddressCellB2)
ic(AddressCellB2)
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB2, timeout=None)
contactName = 1 #getLoc.address
lat1 = 1 #getLoc.latitude
long1 = 1 #getLoc.longitude
Marker1 = MAP.set_marker( lat1, long1, contactName)
Map_Slider = ctk.CTkSlider(TabMap,...
Map_Slider.grid(row=1, column=0, pady=5, padx=5)
更新追溯:
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Traceback (most recent call last):
File "/Users/jawn/Desktop/banana()/EXcel/Excel2Me.py", line 380, in <module>
contactName = getLoc.address
^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'address'
据我所知。除了仅查找 B 列地址列表中的最后一个地址之外,您的问题是由于地址查找而不是从 Excel 读取地址引起的。
尝试将代码分解为更简单的片段以进行调试。您需要做的第一件事就是确认仅查找地址;
例如,尝试运行以下代码;
您可以使用我在第一次运行时包含的地址,如果有效,则将其更改为您要查找的地址,即 B 列中的最后一个地址。
此代码示例将打印“getLoc”对象类型以及相同的每个属性和值。
如果仍然出现错误或属性“地址”。未显示“纬度”和“经度”,那么您可能需要确保安装了最新版本的 geopy。
from geopy.geocoders import Nominatim
AddressCellB = '225 Baker St NW, Atlanta, GA 30313, USA'
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB, timeout=5)
print(f"getLoc object type: {type(getLoc)}")
getLoc_attrib_list = [x for x in dir(getLoc) if not x.startswith(('__','_')) and not callable(getattr(getLoc, x))]
for atty in getLoc_attrib_list:
print(f"Attribute: {atty}, Value: {getattr(getLoc,atty)} ")
上面的输出应该是;
getLoc object type: <class 'geopy.location.Location'>
Attribute: address, Value: Georgia Aquarium, 225, Baker Street Northwest, Atlanta, Fulton County, Georgia, 30313, United States
Attribute: altitude, Value: 0.0
Attribute: latitude, Value: 33.76326745
Attribute: longitude, Value: -84.39511726814364
Attribute: point, Value: 33 45m 47.7628s N, 84 23m 42.4222s W
Attribute: raw, Value: {'place_id': 298584991, 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright', 'osm_type': 'way', 'osm_id': 28912103, 'lat': '33.76326745', 'lon': '-84.39511726814364', 'class': 'tourism', 'type': 'aquarium', 'place_rank': 30, 'importance': 0.39736292979669935, 'addresstype': 'tourism', 'name': 'Georgia Aquarium', 'display_name': 'Georgia Aquarium, 225, Baker Street Northwest, Atlanta, Fulton County, Georgia, 30313, United States', 'boundingbox': ['33.7623777', '33.7643007', '-84.3960032', '-84.3939931']}
如果以上所有检查均正常,那么您可以尝试从 Excel 工作表中读取您的地址。如前所述,如果您要循环访问地址,那么您需要在读取时处理每个地址。
您可以从工作表中读取内容,然后按照 mwe 中的操作进行操作,或者首先将 B 列中的所有地址转储到列表中,然后循环遍历该列表。此时这并不重要,但在读取地址后,例如
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
然后,您必须对 AddressCellB 执行某些操作,否则您将循环到下一个地址,并且前一个 AddressCellB 会丢失,并且只会查找最后一个地址。因此,您需要进行
getLoc = loc.geocode(AddressCellB)
查找和后续的“地址”。 “纬度”和“经度”提取与读取 B 列中每个单元格的循环相同。
因此您的下一个测试代码将类似于
from openpyxl import load_workbook
from geopy.geocoders import Nominatim
wB = load_workbook('HoldingCats(2).xlsx')
wS = wB.active
column_b = wS['B']
for cell in column_b:
AddressCellB = cell.value
print(AddressCellB)
loc = Nominatim(user_agent="Jimmy Wilson")
getLoc = loc.geocode(AddressCellB, timeout=5)
print(f"getLoc object type: {type(getLoc)}")
getLoc_attrib_list = [x for x in dir(getLoc) if not x.startswith(('__','_')) and not callable(getattr(getLoc, x))]
for atty in getLoc_attrib_list:
print(f"Attribute: {atty}, Value: {getattr(getLoc,atty)}")
print('-------------------------------------')
如果该测试正在读取并显示 Excel 工作表中每个地址所需的数据,那么您可以删除属性循环,只提取您需要的数据,然后继续添加映射等。