Repository: pandas-dev/pandas

Issue:
BUG: Excel writer doesn't handle "cols" option correctly
This is an issue that I introduced when fixing #5235.

The `cols` option in `to_excel` no longer works correctly after the fix for the above issue.  For example:

``` python
import pandas as pd

df = pd.DataFrame({'A': ['a', 'a', 'a'],
                   'B': ['b', 'b', 'b']})

df.to_excel('frame.xlsx', sheet_name='Sheet1', cols=['B', 'A'])

```

Gives:

![screenshot](https://f.cloud.github.com/assets/94267/1462277/a4f1cd20-44ed-11e3-96be-993c49f342a6.png)

Note, the headers are changed but not the column data.

I have a proposed fix and test for this. Should I create a new branch/PR or merge it into the Excel MultiIndex PR: #5423



Discussion:
If this is small, might want to do it separately so it can be merged before MI PR.


Resolving patch:
diff --git a/pandas/core/format.py b/pandas/core/format.py
--- a/pandas/core/format.py
+++ b/pandas/core/format.py
@@ -1393,8 +1393,12 @@ def _format_regular_rows(self):
             for idx, idxval in enumerate(index_values):
                 yield ExcelCell(self.rowcounter + idx, 0, idxval, header_style)
 
+        # Get a frame that will account for any duplicates in the column names.
+        col_mapped_frame = self.df.loc[:, self.columns]
+
+        # Write the body of the frame data series by series.
         for colidx in range(len(self.columns)):
-            series = self.df.iloc[:, colidx]
+            series = col_mapped_frame.iloc[:, colidx]
             for i, val in enumerate(series):
                 yield ExcelCell(self.rowcounter + i, colidx + coloffset, val)
 
@@ -1461,8 +1465,12 @@ def _format_hierarchical_rows(self):
                                         header_style)
                     gcolidx += 1
 
+        # Get a frame that will account for any duplicates in the column names.
+        col_mapped_frame = self.df.loc[:, self.columns]
+
+        # Write the body of the frame data series by series.
         for colidx in range(len(self.columns)):
-            series = self.df.iloc[:, colidx]
+            series = col_mapped_frame.iloc[:, colidx]
             for i, val in enumerate(series):
                 yield ExcelCell(self.rowcounter + i, gcolidx + colidx, val)
 


Test patch:
diff --git a/pandas/io/tests/test_excel.py b/pandas/io/tests/test_excel.py
--- a/pandas/io/tests/test_excel.py
+++ b/pandas/io/tests/test_excel.py
@@ -922,11 +922,25 @@ def test_duplicated_columns(self):
             write_frame.columns = colnames
             write_frame.to_excel(path, 'test1')
 
-            read_frame = read_excel(path, 'test1').astype(np.int64)
+            read_frame = read_excel(path, 'test1')
             read_frame.columns = colnames
 
             tm.assert_frame_equal(write_frame, read_frame)
 
+    def test_swapped_columns(self):
+        # Test for issue #5427.
+        _skip_if_no_xlrd()
+
+        with ensure_clean(self.ext) as path:
+            write_frame = DataFrame({'A': [1, 1, 1],
+                                     'B': [2, 2, 2]})
+            write_frame.to_excel(path, 'test1', cols=['B', 'A'])
+
+            read_frame = read_excel(path, 'test1', header=0)
+
+            tm.assert_series_equal(write_frame['A'], read_frame['A'])
+            tm.assert_series_equal(write_frame['B'], read_frame['B'])
+
 
 class OpenpyxlTests(ExcelWriterBase, unittest.TestCase):
     ext = '.xlsx'