Repository: pandas-dev/pandas

Issue:
Minor improvement: Change to_excel "sheet_name" to "sheetname"
pd.read_excel() takes "sheetname" as an argument.
pd.DataFrame.to_excel() takes "sheet_name" as an argument.

For consistency, I think one ought to be changed to match the other.
On my windows installation of pandas 0.16.2, I modified to_excel to take sheetname rather than sheet_name.  All I had to do was locate frame.py within the core directory.  to_excel() is defined here, and sheet_name is written twice in the function and once in the docstring.  

Very new to github so if ideas like these are more appropriately filed through PRs I apologize.



Discussion:
Agree we should make them the same (at least make it available, maybe not necessary to actually deprecate the discouraged alias).

I am only not fully sure if would go with `sheetname` instead of `sheet_name` (we are not always very consistent in the use of `_` to separate words in keywords, but I think the general policy is to use them).

And @saintsfan342000, opening an issue for this is very good! If you get approval, always welcome to open a PR afterwards! 

current (0.20.x) branch appears to mostly use `sheet_name` so propose changing `sheetname` to `sheet_name`.

````
$ git status
On branch 0.20.x
````

49 occurrences of sheet_name in io
````
$ grep -rc sheet_name pandas/io | grep -v 0
pandas/io/excel.py:42
pandas/io/formats/excel.py:3
pandas/io/formats/style.py:2
````

25 occurrences of sheetname in io
````
$ grep -rc sheetname pandas/io | grep -v 0
pandas/io/excel.py:25
````

Resolving patch:
diff --git a/pandas/io/excel.py b/pandas/io/excel.py
--- a/pandas/io/excel.py
+++ b/pandas/io/excel.py
@@ -30,7 +30,7 @@
 import pandas.compat.openpyxl_compat as openpyxl_compat
 from warnings import warn
 from distutils.version import LooseVersion
-from pandas.util._decorators import Appender
+from pandas.util._decorators import Appender, deprecate_kwarg
 from textwrap import fill
 
 __all__ = ["read_excel", "ExcelWriter", "ExcelFile"]
@@ -48,7 +48,7 @@
     The string could be a URL. Valid URL schemes include http, ftp, s3,
     and file. For file URLs, a host is expected. For instance, a local
     file could be file://localhost/path/to/workbook.xlsx
-sheetname : string, int, mixed list of strings/ints, or None, default 0
+sheet_name : string, int, mixed list of strings/ints, or None, default 0
 
     Strings are used for sheet names, Integers are used in zero-indexed
     sheet positions.
@@ -69,6 +69,10 @@
     * [0,1,"Sheet5"] -> 1st, 2nd & 5th sheet as a dictionary of DataFrames
     * None -> All sheets as a dictionary of DataFrames
 
+sheetname : string, int, mixed list of strings/ints, or None, default 0
+    .. deprecated:: 0.21.0
+       Use `sheet_name` instead
+
 header : int, list of ints, default 0
     Row (0-indexed) to use for the column labels of the parsed
     DataFrame. If a list of integers is passed those row positions will
@@ -144,7 +148,7 @@
 Returns
 -------
 parsed : DataFrame or Dict of DataFrames
-    DataFrame from the passed in Excel file.  See notes in sheetname
+    DataFrame from the passed in Excel file.  See notes in sheet_name
     argument for more information on when a Dict of Dataframes is returned.
 """
 
@@ -189,8 +193,9 @@ def get_writer(engine_name):
         raise ValueError("No Excel writer '%s'" % engine_name)
 
 
+@deprecate_kwarg('sheetname', 'sheet_name')
 @Appender(_read_excel_doc)
-def read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0,
+def read_excel(io, sheet_name=0, header=0, skiprows=None, skip_footer=0,
                index_col=None, names=None, parse_cols=None, parse_dates=False,
                date_parser=None, na_values=None, thousands=None,
                convert_float=True, has_index_names=None, converters=None,
@@ -201,7 +206,7 @@ def read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0,
         io = ExcelFile(io, engine=engine)
 
     return io._parse_excel(
-        sheetname=sheetname, header=header, skiprows=skiprows, names=names,
+        sheetname=sheet_name, header=header, skiprows=skiprows, names=names,
         index_col=index_col, parse_cols=parse_cols, parse_dates=parse_dates,
         date_parser=date_parser, na_values=na_values, thousands=thousands,
         convert_float=convert_float, has_index_names=has_index_names,
@@ -266,7 +271,7 @@ def __init__(self, io, **kwds):
     def __fspath__(self):
         return self._io
 
-    def parse(self, sheetname=0, header=0, skiprows=None, skip_footer=0,
+    def parse(self, sheet_name=0, header=0, skiprows=None, skip_footer=0,
               names=None, index_col=None, parse_cols=None, parse_dates=False,
               date_parser=None, na_values=None, thousands=None,
               convert_float=True, has_index_names=None,
@@ -279,7 +284,7 @@ def parse(self, sheetname=0, header=0, skiprows=None, skip_footer=0,
         docstring for more info on accepted parameters
         """
 
-        return self._parse_excel(sheetname=sheetname, header=header,
+        return self._parse_excel(sheetname=sheet_name, header=header,
                                  skiprows=skiprows, names=names,
                                  index_col=index_col,
                                  has_index_names=has_index_names,


Test patch:
diff --git a/pandas/tests/io/test_excel.py b/pandas/tests/io/test_excel.py
--- a/pandas/tests/io/test_excel.py
+++ b/pandas/tests/io/test_excel.py
@@ -544,6 +544,18 @@ def test_date_conversion_overflow(self):
         result = self.get_exceldf('testdateoverflow')
         tm.assert_frame_equal(result, expected)
 
+    def test_sheet_name_and_sheetname(self):
+        # GH10559: Minor improvement: Change "sheet_name" to "sheetname"
+        # GH10969: DOC: Consistent var names (sheetname vs sheet_name)
+        # GH12604: CLN GH10559 Rename sheetname variable to sheet_name
+        dfref = self.get_csv_refdf('test1')
+        df1 = self.get_exceldf('test1', sheet_name='Sheet1')    # doc
+        with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
+            df2 = self.get_exceldf('test1', sheetname='Sheet2')  # bkwrd compat
+
+        tm.assert_frame_equal(df1, dfref, check_names=False)
+        tm.assert_frame_equal(df2, dfref, check_names=False)
+
 
 class XlrdTests(ReadingTestsBase):
     """