Repository: pyvista/pyvista

Issue:
`add_field_data` breaks `_repr_html_`
### Describe the bug, what's wrong, and what you expected.

Adding a field data (e.g., through ``user_dict`` in my case) breaks the method ``_repr_html_()``.

### Steps to reproduce the bug.

```python
import pyvista

grid = pyvista.Dodecahedron()
grid._repr_html_()  # this works
grid.add_field_data("foo", "bar")
grid._repr_html_()
```

The last line gives the error:

```python
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File c:\Users\keurf\Git\pyvista\bug.py:12
     [10](file:///C:/Users/keurf/Git/pyvista/bug.py:10) grid._repr_html_()  # this works
     [11](file:///C:/Users/keurf/Git/pyvista/bug.py:11) grid.add_field_data("foo", "bar")
---> [12](file:///C:/Users/keurf/Git/pyvista/bug.py:12) grid._repr_html_()

File c:\Users\keurf\Git\pyvista\pyvista\core\dataset.py:2268, in DataSet._repr_html_(self)
   [2266](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2266)     fmt += format_array(key, arr, 'Cells')
   [2267](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2267) for key, arr in self.field_data.items():
-> [2268](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2268)     fmt += format_array(key, arr, 'Fields')
   [2270](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2270) fmt += "</table>\n"
   [2271](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2271) fmt += "\n"

File c:\Users\keurf\Git\pyvista\pyvista\core\dataset.py:2255, in DataSet._repr_html_.<locals>.format_array(name, arr, field)
   [2253](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2253) def format_array(name, arr, field):
   [2254](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2254)     """Format array information for printing (internal helper)."""
-> [2255](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2255)     dl, dh = self.get_data_range(arr)
   [2256](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2256)     dl = pyvista.FLOAT_FORMAT.format(dl)
   [2257](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:2257)     dh = pyvista.FLOAT_FORMAT.format(dh)

File c:\Users\keurf\Git\pyvista\pyvista\core\dataset.py:888, in DataSet.get_data_range(self, arr_var, preference)
    [886](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:886) if isinstance(arr_var, str):
    [887](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:887)     name = arr_var
--> [888](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:888)     arr = get_array(self, name, preference=preference, err=True)
    [889](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:889) else:
    [890](file:///C:/Users/keurf/Git/pyvista/pyvista/core/dataset.py:890)     arr = arr_var

File c:\Users\keurf\Git\pyvista\pyvista\core\utilities\arrays.py:309, in get_array(mesh, name, preference, err)
    [307](file:///C:/Users/keurf/Git/pyvista/pyvista/core/utilities/arrays.py:307)     return farr
    [308](file:///C:/Users/keurf/Git/pyvista/pyvista/core/utilities/arrays.py:308) elif err:
--> [309](file:///C:/Users/keurf/Git/pyvista/pyvista/core/utilities/arrays.py:309)     raise KeyError(f'Data array ({name}) not present in this dataset.')
    [310](file:///C:/Users/keurf/Git/pyvista/pyvista/core/utilities/arrays.py:310) return None

KeyError: 'Data array (foo) not present in this dataset.'
```

### System Information

```shell
--------------------------------------------------------------------------------
  Date: Mon Aug 19 18:51:12 2024 Romance Daylight Time

                OS : Windows (11 10.0.26100 SP0 Multiprocessor Free)
            CPU(s) : 16
           Machine : AMD64
      Architecture : 64bit
               RAM : 15.7 GiB
       Environment : Jupyter
        GPU Vendor : Intel
      GPU Renderer : Intel(R) Iris(R) Xe Graphics
       GPU Version : 4.5.0 - Build 31.0.101.5592
  MathText Support : False

  Python 3.12.4 | packaged by Anaconda, Inc. | (main, Jun 18 2024, 15:03:56)
  [MSC v.1929 64 bit (AMD64)]

           pyvista : 0.45.dev0
               vtk : 9.3.1
             numpy : 1.26.4
        matplotlib : 3.9.1.post1
            scooby : 0.10.0
             pooch : 1.8.2
            pillow : 10.4.0
           imageio : 2.34.2
             PyQt5 : 5.15.10
           IPython : 8.26.0
          colorcet : 3.1.0
           cmocean : 4.0.3
        ipywidgets : 8.1.3
             scipy : 1.14.0
              tqdm : 4.66.5
            meshio : 5.3.5
        jupyterlab : 4.0.11
    pytest_pyvista : 0.1.8
             trame : 3.6.3
      trame_client : 3.2.1
      trame_server : 3.0.3
         trame_vtk : 2.8.10
     trame_vuetify : 2.6.2
      nest_asyncio : 1.6.0

  Intel(R) oneAPI Math Kernel Library Version 2023.1-Product Build 20230303
  for Intel(R) 64 architecture applications
--------------------------------------------------------------------------------
```


### Screenshots

_No response_

Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/pyvista/pyvista/pull/6541?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 91.45%. Comparing base [(`010b33a`)](https://app.codecov.io/gh/pyvista/pyvista/commit/010b33a3d420222c2223293a48110e8f699cc597?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista) to head [(`dbe8907`)](https://app.codecov.io/gh/pyvista/pyvista/commit/dbe8907bb7af92d139c30b0ebbfe5ba2b7147fcb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista).

> :exclamation:  There is a different number of reports uploaded between BASE (010b33a) and HEAD (dbe8907). Click for more details.
> 
> <details><summary>HEAD has 11 uploads less than BASE</summary>
>
>| Flag | BASE (010b33a) | HEAD (dbe8907) |
>|------|------|------|
>||12|1|
></details>

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #6541      +/-   ##
==========================================
- Coverage   97.34%   91.45%   -5.90%     
==========================================
  Files         143      143              
  Lines       27358    27360       +2     
==========================================
- Hits        26632    25022    -1610     
- Misses        726     2338    +1612     
```

</details>
pyvista-bot: <!-- NETLIFY DEPLOY COMMENT GENERATED BY ACTIONS_NETLIFY - APP ID SHA256: d3574f413fe51079937885070831e027ca5b10f7facb9e609494e0a481a31f79 -->
🚀 Deployed on https://66c3a4b560349130f4d4eec8--pyvista-dev.netlify.app

Patch:
diff --git a/pyvista/core/dataset.py b/pyvista/core/dataset.py
index 4b61fe46..606bb01d 100644
--- a/pyvista/core/dataset.py
+++ b/pyvista/core/dataset.py
@@ -2240,6 +2240,10 @@ class DataSet(DataSetFilters, DataObject):
 
             def format_array(name, arr, field):
                 """Format array information for printing (internal helper)."""
+                if isinstance(arr, str):
+                    # Convert string scalar into a numpy array. Otherwise, get_data_range
+                    # will treat the string as an array name, not an array value.
+                    arr = np.array(arr)
                 dl, dh = self.get_data_range(arr)
                 dl = pyvista.FLOAT_FORMAT.format(dl)
                 dh = pyvista.FLOAT_FORMAT.format(dh)


Test patch:
diff --git a/tests/core/test_dataset.py b/tests/core/test_dataset.py
index b08059a0..8a25d141 100644
--- a/tests/core/test_dataset.py
+++ b/tests/core/test_dataset.py
@@ -527,6 +527,13 @@ def test_html_repr(grid):
     assert grid._repr_html_() is not None
 
 
+def test_html_repr_string_scalar(grid):
+    array_data = "data"
+    array_name = "name"
+    grid.add_field_data(array_data, array_name)
+    assert grid._repr_html_() is not None
+
+
 @pytest.mark.parametrize('html', [True, False])
 @pytest.mark.parametrize('display', [True, False])
 def test_print_repr(grid, display, html):