code: def xlsx_cells(
      path: Union[str, Workbook],
      sheetnames: Union[str, list, tuple] = None,
      start_point: Union[str, int] = None,
      end_point: Union[str, int] = None,
      read_only: bool = True,
      include_blank_cells: bool = True,
      fill: bool = False,
      font: bool = False,
      alignment: bool = False,
      border: bool = False,
      protection: bool = False,
      comment: bool = False,
      **kwargs: Any,
  ) -> Union[dict, pd.DataFrame]:
      """Imports data from spreadsheet without coercing it into a rectangle.
  
      Each cell is represented by a row in a dataframe, and includes the
      cell's coordinates, the value, row and column position.
      The cell formatting (fill, font, border, etc) can also be accessed;
      usually this is returned as a dictionary in the cell, and the specific
      cell format attribute can be accessed using `pd.Series.str.get`.
  
      Inspiration for this comes from R's [tidyxl][link] package.
      [link]: https://nacnudus.github.io/tidyxl/reference/tidyxl.html
  
      Examples:
          >>> import pandas as pd
          >>> from janitor import xlsx_cells
          >>> pd.set_option("display.max_columns", None)
          >>> pd.set_option("display.expand_frame_repr", False)
          >>> pd.set_option("max_colwidth", None)
          >>> filename = "../pyjanitor/tests/test_data/worked-examples.xlsx"
  
          Each cell is returned as a row:
  
          >>> xlsx_cells(filename, sheetnames="highlights")
              value internal_value coordinate  row  column data_type  is_date number_format
          0     Age            Age         A1    1       1         s    False       General
          1  Height         Height         B1    1       2         s    False       General
          2       1              1         A2    2       1         n    False       General
          3       2              2         B2    2       2         n    False       General
          4       3              3         A3    3       1         n    False       General
          5       4              4         B3    3       2         n    False       General
          6       5              5         A4    4       1         n    False       General
          7       6              6         B4    4       2         n    False       General
  
          Access cell formatting such as fill:
  
          >>> out=xlsx_cells(filename, sheetnames="highlights", fill=True).select("value", "fill", axis='columns')
          >>> out
              value                                                                                                                                              fill
          0     Age     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
          1  Height     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
          2       1     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
          3       2     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
          4       3  {'patternType': 'solid', 'fgColor': {'rgb': 'FFFFFF00', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': 'FFFFFF00', 'type': 'rgb', 'tint': 0.0}}
          5       4  {'patternType': 'solid', 'fgColor': {'rgb': 'FFFFFF00', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': 'FFFFFF00', 'type': 'rgb', 'tint': 0.0}}
          6       5     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
          7       6     {'patternType': None, 'fgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}, 'bgColor': {'rgb': '00000000', 'type': 'rgb', 'tint': 0.0}}
  
          Specific cell attributes can be accessed by using Pandas' `series.str.get`:
  
          >>> out.fill.str.get("fgColor").str.get("rgb")
          0    00000000
          1    00000000
          2    00000000
          3    00000000
          4    FFFFFF00
          5    FFFFFF00
          6    00000000
          7    00000000
          Name: fill, dtype: object
  
      Args:
          path: Path to the Excel File. It can also be an openpyxl Workbook.
          sheetnames: Names of the sheets from which the cells are to be extracted.
              If `None`, all the sheets in the file are extracted;
              if it is a string, or list or tuple, only the specified sheets are extracted.
          start_point: Start coordinates of the Excel sheet. This is useful
              if the user is only interested in a subsection of the sheet.
              If `start_point` is provided, `end_point` must be provided as well.
          end_point: End coordinates of the Excel sheet. This is useful
              if the user is only interested in a subsection of the sheet.
              If `end_point` is provided, `start_point` must be provided as well.
          read_only: Determines if the entire file is loaded in memory,
              or streamed. For memory efficiency, read_only should be set to `True`.
              Some cell properties like `comment`, can only be accessed by
              setting `read_only` to `False`.
          include_blank_cells: Determines if cells without a value should be included.
          fill: If `True`, return fill properties of the cell.
              It is usually returned as a dictionary.
          font: If `True`, return font properties of the cell.
              It is usually returned as a dictionary.
          alignment: If `True`, return alignment properties of the cell.
              It is usually returned as a dictionary.
          border: If `True`, return border properties of the cell.
              It is usually returned as a dictionary.
          protection: If `True`, return protection properties of the cell.
              It is usually returned as a dictionary.
          comment: If `True`, return comment properties of the cell.
              It is usually returned as a dictionary.
          **kwargs: Any other attributes of the cell, that can be accessed from openpyxl.
  
      Raises:
          ValueError: If kwargs is provided, and one of the keys is a default column.
          AttributeError: If kwargs is provided and any of the keys
              is not a openpyxl cell attribute.
  
      Returns:
          A pandas DataFrame, or a dictionary of DataFrames.
      """  # noqa : E501
  
      try:
          from openpyxl import load_workbook
          from openpyxl.cell.cell import Cell
          from openpyxl.cell.read_only import ReadOnlyCell
          from openpyxl.workbook.workbook import Workbook
      except ImportError:
          import_message(
              submodule="io",
              package="openpyxl",
              conda_channel="conda-forge",
              pip_install=True,
          )
  
      path_is_workbook = isinstance(path, Workbook)
      if not path_is_workbook:
          # for memory efficiency, read_only is set to True
          # if comments is True, read_only has to be False,
          # as lazy loading is not enabled for comments
          if comment and read_only:
              raise ValueError(
                  "To access comments, kindly set 'read_only' to False."
              )
          path = load_workbook(
              filename=path, read_only=read_only, keep_links=False
          )
      # start_point and end_point applies if the user is interested in
      # only a subset of the Excel File and knows the coordinates
      if start_point or end_point:
          check("start_point", start_point, [str, int])
          check("end_point", end_point, [str, int])
  
      defaults = (
          "value",
          "internal_value",
          "coordinate",
          "row",
          "column",
          "data_type",
          "is_date",
          "number_format",
      )
  
      parameters = {
          "fill": fill,
          "font": font,
          "alignment": alignment,
          "border": border,
          "protection": protection,
          "comment": comment,
      }
  
      if kwargs:
          if path_is_workbook:
              if path.read_only:
                  _cell = ReadOnlyCell
              else:
                  _cell = Cell
          else:
              if read_only:
                  _cell = ReadOnlyCell
              else:
                  _cell = Cell
  
          attrs = {
              attr
              for attr, _ in inspect.getmembers(
                  _cell, not (inspect.isroutine)
              )
              if not attr.startswith("_")
          }
  
          for key in kwargs:
              if key in defaults:
                  raise ValueError(
                      f"{key} is part of the default attributes "
                      "returned as a column."
                  )
              elif key not in attrs:
                  raise AttributeError(
                      f"{key} is not a recognized attribute of {_cell}."
                  )
          parameters.update(kwargs)
  
      if not sheetnames:
          sheetnames = path.sheetnames
      elif isinstance(sheetnames, str):
          sheetnames = [sheetnames]
      else:
          check("sheetnames", sheetnames, [str, list, tuple])
  
      out = {
          sheetname: _xlsx_cells(
              path[sheetname],
              defaults,
              parameters,
              start_point,
              end_point,
              include_blank_cells,
          )
          for sheetname in sheetnames
      }
      if len(out) == 1:
          _, out = out.popitem()
  
      if (not path_is_workbook) and path.read_only:
          path.close()
  
      return out
  
file_path: pyjanitor/janitor/io.py
imports: from __future__ import annotations
  import inspect
  import os
  import subprocess
  from collections import defaultdict
  from glob import glob
  from io import StringIO
  from itertools import chain
  from typing import TYPE_CHECKING, Any, Iterable, NamedTuple, Union
  import pandas
  from .errors import JanitorError
  from .utils import check, deprecated_alias, import_message
label_desc: Use image node_id 4 for calling a global function with example usage: xlsx_cells(path, sheetnames, start_point, end_point, read_only, include_blank_cells, fill, font, alignment, border, protection, comment) and returns: out