使用 Geopy 在从电子表格中提取的地址上放置 (tkintermapview) 标记

问题描述 投票:0回答:1

我正在尝试从电子表格获取地址.. 将这些地址转换为纬度和经度.. 然后将标记添加到 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'
python openpyxl geopy geocoder tkintermapview
1个回答
0
投票

据我所知。除了仅查找 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 工作表中每个地址所需的数据,那么您可以删除属性循环,只提取您需要的数据,然后继续添加映射等。

© www.soinside.com 2019 - 2024. All rights reserved.