diff --git a/eeschema/dialogs/dialog_lib_symbol_properties.cpp b/eeschema/dialogs/dialog_lib_symbol_properties.cpp
index c4775ae73f..001c636af0 100644
--- a/eeschema/dialogs/dialog_lib_symbol_properties.cpp
+++ b/eeschema/dialogs/dialog_lib_symbol_properties.cpp
@@ -87,11 +87,6 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
     SYMBOL_EDITOR_SETTINGS* cfg = m_Parent->GetSettings();
     m_grid->ShowHideColumns( cfg->m_EditSymbolVisibleColumns );
 
-    wxGridCellAttr* attr = new wxGridCellAttr;
-    attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ),
-                                               m_embeddedFiles->GetLocalFiles() ) );
-    m_grid->SetAttr( DATASHEET_FIELD, FDC_VALUE, attr );
-
     m_SymbolNameCtrl->SetValidator( FIELD_VALIDATOR( VALUE_FIELD ) );
 
     // Configure button logos
diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp
index 75a692c7b3..bf3f29bdcb 100644
--- a/eeschema/dialogs/dialog_symbol_fields_table.cpp
+++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp
@@ -221,7 +221,11 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
     m_fieldsCtrl->SetIndent( 0 );
 
     m_filter->SetDescriptiveText( _( "Filter" ) );
-    m_dataModel = new FIELDS_EDITOR_GRID_DATA_MODEL( m_symbolsList );
+
+    wxGridCellAttr* attr = new wxGridCellAttr;
+    attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ),
+                                               &m_parent->Schematic() ) );
+    m_dataModel = new FIELDS_EDITOR_GRID_DATA_MODEL( m_symbolsList, attr );
 
     LoadFieldNames();   // loads rows into m_fieldsCtrl and columns into m_dataModel
 
@@ -294,9 +298,7 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
             BOM_FIELD field;
             field.name = fieldName;
             field.show = !fieldName.StartsWith( wxT( "__" ), &field.name );
-            field.groupBy = std::find( m_job->m_fieldsGroupBy.begin(), m_job->m_fieldsGroupBy.end(),
-                                       field.name )
-                            != m_job->m_fieldsGroupBy.end();
+            field.groupBy = alg::contains( m_job->m_fieldsGroupBy, field.name );
 
             if( ( m_job->m_fieldsLabels.size() > i ) && !m_job->m_fieldsLabels[i].IsEmpty() )
                 field.label = m_job->m_fieldsLabels[i];
@@ -413,43 +415,43 @@ void DIALOG_SYMBOL_FIELDS_TABLE::SetupColumnProperties( int aCol )
     if( m_dataModel->ColIsReference( aCol ) )
     {
         attr->SetReadOnly();
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FOOTPRINT_FIELD ) )
     {
         attr->SetEditor( new GRID_CELL_FPID_EDITOR( this, wxEmptyString ) );
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( DATASHEET_FIELD ) )
     {
         // set datasheet column viewer button
         attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ),
                                                    &m_parent->Schematic() ) );
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else if( m_dataModel->ColIsQuantity( aCol ) || m_dataModel->ColIsItemNumber( aCol ) )
     {
         attr->SetReadOnly();
-        m_grid->SetColAttr( aCol, attr );
         attr->SetAlignment( wxALIGN_RIGHT, wxALIGN_CENTER );
         attr->SetRenderer( new wxGridCellNumberRenderer() );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else if( m_dataModel->ColIsAttribute( aCol ) )
     {
         attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
         attr->SetRenderer( new wxGridCellBoolRenderer() );
         attr->SetReadOnly();    // not really; we delegate interactivity to GRID_TRICKS
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else if( IsTextVar( m_dataModel->GetColFieldName( aCol ) ) )
     {
         attr->SetReadOnly();
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
     else
     {
         attr->SetEditor( m_grid->GetDefaultEditor() );
-        m_grid->SetColAttr( aCol, attr );
+        m_dataModel->SetColAttr( attr, aCol );
     }
 }
 
diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp
index 32b54240a8..f95b05bfb7 100644
--- a/eeschema/eeschema_jobs_handler.cpp
+++ b/eeschema/eeschema_jobs_handler.cpp
@@ -530,7 +530,7 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
         m_reporter->Report( _( "Warning: duplicate sheet names.\n" ), RPT_SEVERITY_WARNING );
 
     // Build our data model
-    FIELDS_EDITOR_GRID_DATA_MODEL dataModel( referenceList );
+    FIELDS_EDITOR_GRID_DATA_MODEL dataModel( referenceList, nullptr );
 
     // Mandatory fields + quantity virtual field first
     for( int fieldId : MANDATORY_FIELDS )
diff --git a/eeschema/fields_data_model.cpp b/eeschema/fields_data_model.cpp
index a4d6ea3a05..98bccaa58c 100644
--- a/eeschema/fields_data_model.cpp
+++ b/eeschema/fields_data_model.cpp
@@ -175,6 +175,29 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( int aRow, int aCol )
 }
 
 
+wxGridCellAttr* FIELDS_EDITOR_GRID_DATA_MODEL::GetAttr( int aRow, int aCol,
+                                                        wxGridCellAttr::wxAttrKind aKind )
+{
+    if( GetColFieldName( aCol ) == GetCanonicalFieldName( DATASHEET_FIELD )
+            || IsURL( GetValue( m_rows[aRow], aCol ) ) )
+    {
+        if( m_urlEditor )
+        {
+            m_urlEditor->IncRef();
+            return enhanceAttr( m_urlEditor, aRow, aCol, aKind );
+        }
+    }
+
+    if( m_colAttrs[aCol] )
+    {
+        m_colAttrs[aCol]->IncRef();
+        return enhanceAttr( m_colAttrs[aCol], aRow, aCol, aKind );
+    }
+
+    return nullptr;
+}
+
+
 wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( const DATA_MODEL_ROW& group, int aCol,
                                                   const wxString& refDelimiter,
                                                   const wxString& refRangeDelimiter,
diff --git a/eeschema/fields_data_model.h b/eeschema/fields_data_model.h
index 7f7d5d6883..0c771c2466 100644
--- a/eeschema/fields_data_model.h
+++ b/eeschema/fields_data_model.h
@@ -1,7 +1,6 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 2023 <author>
  * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  *
  * This program is free software: you can redistribute it and/or modify it
@@ -19,6 +18,7 @@
  */
 #include <sch_reference_list.h>
 #include <wx/grid.h>
+#include <widgets/wx_grid.h>
 
 // The field name in the data model (translated)
 #define DISPLAY_NAME_COLUMN   0
@@ -70,7 +70,7 @@ struct DATA_MODEL_COL
 };
 
 
-class FIELDS_EDITOR_GRID_DATA_MODEL : public wxGridTableBase
+class FIELDS_EDITOR_GRID_DATA_MODEL : public WX_GRID_TABLE_BASE
 {
 public:
     enum SCOPE : int
@@ -80,7 +80,7 @@ public:
         SCOPE_SHEET_RECURSIVE = 2
     };
 
-    FIELDS_EDITOR_GRID_DATA_MODEL( SCH_REFERENCE_LIST& aSymbolsList ) :
+    FIELDS_EDITOR_GRID_DATA_MODEL( SCH_REFERENCE_LIST& aSymbolsList, wxGridCellAttr* aURLEditor ) :
             m_symbolsList( aSymbolsList ),
             m_edited( false ),
             m_sortColumn( 0 ),
@@ -89,11 +89,21 @@ public:
             m_groupingEnabled( false ),
             m_excludeDNP( false ),
             m_includeExcluded( false ),
-            m_rebuildsEnabled( true )
+            m_rebuildsEnabled( true ),
+            m_urlEditor( aURLEditor )
     {
         m_symbolsList.SplitReferences();
     }
 
+    ~FIELDS_EDITOR_GRID_DATA_MODEL() override
+    {
+        if( m_urlEditor )
+            m_urlEditor->DecRef();
+
+        for( const auto& [col, attr] : m_colAttrs )
+            wxSafeDecRef( attr );
+    }
+
     static const wxString QUANTITY_VARIABLE;
     static const wxString ITEM_NUMBER_VARIABLE;
 
@@ -154,6 +164,8 @@ public:
     }
 
     wxString GetValue( int aRow, int aCol ) override;
+    wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override;
+
     wxString GetValue( const DATA_MODEL_ROW& group, int aCol,
                        const wxString& refDelimiter = wxT( ", " ),
                        const wxString& refRangDelimiter = wxT( "-" ),
@@ -265,6 +277,11 @@ public:
     void RemoveSymbol( const SCH_SYMBOL& aSymbol );
     void UpdateReferences( const SCH_REFERENCE_LIST& aRefs );
 
+    void SetColAttr( wxGridCellAttr* aAttr, int aCol ) override
+    {
+        wxSafeDecRef( m_colAttrs[aCol] );
+        m_colAttrs[aCol] = aAttr;
+    }
 
 private:
     static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
@@ -304,6 +321,9 @@ protected:
     bool               m_includeExcluded;
     bool               m_rebuildsEnabled;
 
+    wxGridCellAttr*                m_urlEditor;
+    std::map<int, wxGridCellAttr*> m_colAttrs;
+
     std::vector<DATA_MODEL_COL> m_cols;
     std::vector<DATA_MODEL_ROW> m_rows;
 
diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp
index a0fc125f70..6ae35c8448 100644
--- a/eeschema/fields_grid_table.cpp
+++ b/eeschema/fields_grid_table.cpp
@@ -604,7 +604,7 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
             const TEMPLATE_FIELDNAME* templateFn =
                     settings ? settings->m_TemplateFieldNames.GetFieldName( fn ) : nullptr;
 
-            if( templateFn && templateFn->m_URL )
+            if( ( templateFn && templateFn->m_URL ) || field.IsHypertext() )
             {
                 m_urlAttr->IncRef();
                 return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h
index 1cf2c24188..f1ea8e04f3 100644
--- a/eeschema/sch_field.h
+++ b/eeschema/sch_field.h
@@ -31,6 +31,7 @@
 #include <sch_item.h>
 #include <template_fieldnames.h>
 #include <general.h>
+#include <string_utils.h>
 #include "scintilla_tricks.h"
 
 class SCH_EDIT_FRAME;
@@ -103,7 +104,10 @@ public:
 
     bool IsHypertext() const override
     {
-        return GetCanonicalName() == wxT( "Intersheetrefs" );
+        if( GetCanonicalName() == wxT( "Intersheetrefs" ) )
+            return true;
+
+        return IsURL( GetShownText( false ) );
     }
 
     void DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const override;
diff --git a/pcbnew/pcb_field.cpp b/pcbnew/pcb_field.cpp
index c5b3703e86..31aba4ddba 100644
--- a/pcbnew/pcb_field.cpp
+++ b/pcbnew/pcb_field.cpp
@@ -28,6 +28,7 @@
 #include <i18n_utility.h>
 #include <pcb_painter.h>
 #include <api/board/board_types.pb.h>
+#include <string_utils.h>
 
 
 PCB_FIELD::PCB_FIELD( FOOTPRINT* aParent, int aFieldId, const wxString& aName ) :
@@ -142,6 +143,12 @@ bool PCB_FIELD::IsMandatory() const
 }
 
 
+bool PCB_FIELD::IsHypertext() const
+{
+    return IsURL( GetShownText( false ) );
+}
+
+
 wxString PCB_FIELD::GetTextTypeDescription() const
 {
     if( IsMandatory() )
diff --git a/pcbnew/pcb_field.h b/pcbnew/pcb_field.h
index b6dcdb08eb..9d536a09cd 100644
--- a/pcbnew/pcb_field.h
+++ b/pcbnew/pcb_field.h
@@ -72,6 +72,8 @@ public:
 
     bool IsMandatory() const;
 
+    bool IsHypertext() const;
+
     wxString GetTextTypeDescription() const override;
 
     wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override;
diff --git a/pcbnew/pcb_fields_grid_table.cpp b/pcbnew/pcb_fields_grid_table.cpp
index 1915783609..9151b481af 100644
--- a/pcbnew/pcb_fields_grid_table.cpp
+++ b/pcbnew/pcb_fields_grid_table.cpp
@@ -223,7 +223,7 @@ wxGridCellAttr* PCB_FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol,
             m_valueAttr->IncRef();
             return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
         }
-        else if( field.GetId() == DATASHEET_FIELD )
+        else if( field.GetId() == DATASHEET_FIELD || field.IsHypertext() )
         {
             m_urlAttr->IncRef();
             return enhanceAttr( m_urlAttr, aRow, aCol, aKind );