Repository: pandas-dev/pandas

Issue:
read_excel drops columns when reading a one row file with a MultiIndex
I'm seeing the weirdest error.

When I read an .xlsx excel file with only one row (example below)...
![image](https://cloud.githubusercontent.com/assets/6059365/5653615/b8ae57ca-96b3-11e4-8a9d-25e716d2a122.png)
... and try to set the `index_col`, then pandas incorrectly reads the columns:

I.e. for a file with only one row, column headers A, B, C, D, E, F

``` python
pandas.read_excel(filename, 'Sheet1', index_col=['A', 'B', 'C'])
```

Yields
![image](https://cloud.githubusercontent.com/assets/6059365/5653647/0f8f049a-96b4-11e4-89bc-6d5d355dbde8.png)
(I get an index with columns A, B, C, and a dataframe with columns B, D, F - what happened to E?)

Note that if I don't use `index_col`, I get a dataframe with columns A-F as expected. Likewise, if I add a row of actual data, the dataframe loads as expected.

Relevant versions:
`pandas version 0.15.1 running on 2.7.7 |Anaconda 2.0.1 (64-bit)| (default, Jun 11 2014, 10:40:02) [MSC v.1500 64 bit (AMD64)]`
`xlrd.__VERSION__`=0.9.3



Discussion:
I can confirm this with 0.15.2

Would have to dig into it (unlikely to have time soon), but #10184 might suggest how this could be fixed, as the issues seem similar.


Resolving patch:
diff --git a/pandas/io/excel.py b/pandas/io/excel.py
--- a/pandas/io/excel.py
+++ b/pandas/io/excel.py
@@ -634,14 +634,17 @@ def _parse_cell(cell_contents, cell_typ):
                 else:
                     offset = 1 + max(header)
 
-                for col in index_col:
-                    last = data[offset][col]
-
-                    for row in range(offset + 1, len(data)):
-                        if data[row][col] == '' or data[row][col] is None:
-                            data[row][col] = last
-                        else:
-                            last = data[row][col]
+                # Check if we have an empty dataset
+                # before trying to collect data.
+                if offset < len(data):
+                    for col in index_col:
+                        last = data[offset][col]
+
+                        for row in range(offset + 1, len(data)):
+                            if data[row][col] == '' or data[row][col] is None:
+                                data[row][col] = last
+                            else:
+                                last = data[row][col]
 
             has_index_names = is_list_like(header) and len(header) > 1
 


Test patch:
diff --git a/pandas/tests/io/data/test1.xls b/pandas/tests/io/data/test1.xls
Binary files a/pandas/tests/io/data/test1.xls and b/pandas/tests/io/data/test1.xls differ
diff --git a/pandas/tests/io/data/test1.xlsm b/pandas/tests/io/data/test1.xlsm
Binary files a/pandas/tests/io/data/test1.xlsm and b/pandas/tests/io/data/test1.xlsm differ
diff --git a/pandas/tests/io/data/test1.xlsx b/pandas/tests/io/data/test1.xlsx
Binary files a/pandas/tests/io/data/test1.xlsx and b/pandas/tests/io/data/test1.xlsx differ
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
@@ -235,6 +235,16 @@ def test_index_col_label_error(self, ext):
             self.get_exceldf("test1", ext, "Sheet1", index_col=["A"],
                              usecols=["A", "C"])
 
+    def test_index_col_empty(self, ext):
+        # see gh-9208
+        result = self.get_exceldf("test1", ext, "Sheet3",
+                                  index_col=["A", "B", "C"])
+        expected = DataFrame(columns=["D", "E", "F"],
+                             index=MultiIndex(levels=[[]] * 3,
+                                              labels=[[]] * 3,
+                                              names=["A", "B", "C"]))
+        tm.assert_frame_equal(result, expected)
+
     def test_usecols_pass_non_existent_column(self, ext):
         msg = ("Usecols do not match columns, "
                "columns expected but not found: " + r"\['E'\]")