Repository: psychopy/psychopy

Issue:
MultiStairHandler method saveAsExcel creates too many files
Hi,

This is a minor issue but I have a MultiStairhandler with 4 conditions (or 4 interleaved staircases).

When I'm done with the staircases, I call `staircases.saveAsExcel`. This produces **2** `.xlsx` files, with the first staircase being in the first spreadsheet, and the three subsequent staircases being in the second spreadsheet. It looks like this:
![image](https://cloud.githubusercontent.com/assets/4092425/16945453/12a14a48-4d9d-11e6-99e9-96eb2fdb0482.png)

![image](https://cloud.githubusercontent.com/assets/4092425/16945469/21d4602c-4d9d-11e6-8c24-e5bc13a95020.png)

As you can see, the staircase labels are all unique. Only one of the staircases is in a separate `.xlsx` file.

For reference, I am using:
psychopy version 1.82.1
python version 2.7.11 (via anaconda 4.0.0, 32 bit)



Discussion:
Does this problem still occur with the latest version of PsychoPy?

Hi,

thanks for taking a look at this. However, there seem to be a whole host of new issues with this method.

With PsychoPy 1.84.2 (and openpyxl 2.4.0), I am now getting an ImportError when trying to call saveAsExcel:
`ImportError: openpyxl is required for saving files in Excel (xlsx) format, but was not found.`

I did a little digging, and found that this seems to stem from line 29 in `data.py`:
`from openpyxl.cell import get_column_letter`

as far as I can tell, `get_column_letter` sits in `openpyxl.utils.cell`:
http://openpyxl.readthedocs.io/en/default/api/openpyxl.utils.cell.html#openpyxl.utils.cell.get_column_letter

Now, if I change line 29 to import from `openpyxl.utils.cell` instead, I don't get the ImportError anymore. However, I get a different error instead:

`File "[local python path]/data.py", line 3326, in saveAsExcel:`
`ew = ExcelWriter(workbook=wb)`
`TypeError: __init__() takes exactly 3 arguments (2 given)`

I'll do some more digging to see what arguments are missing here, but it seems some update to openpyxl has broken this method?

Cheers,
Jan

Just to add to that, `ExcelWriter` seems to require two arguments, workbook and archive:
http://openpyxl.readthedocs.io/en/default/_modules/openpyxl/writer/excel.html#ExcelWriter

I'm not sure what archive is, though.

Hi @janfreyberg, thanks for your feedback. Could you please provide a minimal code example to reproduce the problem?

Yes, it looks like a change in the openpyxl APA. It seems we don't need to use the ExcelWriter explicitly at all though. From the docs here:
http://openpyxl.readthedocs.io/en/default/tutorial.html#saving-to-a-file
it looks like we can forget of any mention of it and just do `workbook.save(filename)` rather than 

```
ew = ExcelWriter(workbook); 
ew.save(filename)
```

I commented out the use of ExcelWriter and instead changed it to wb.save(filename) like you suggested. This fixes the problems with writing to excel, as it now creates excel files without error again.

However, it looks like the issue with multiple Excel files being created is still present.

This is a minimal example that reproduces the issue:
https://gist.github.com/janfreyberg/fece6b94493e66f5d98644fcc9ff9037

Thanks, I will look into this later today. 

## 

Sent from my phone, please excuse brevity and erroneous auto-correct.

> On 14 Oct 2016, at 10:29, Jan Freyberg notifications@github.com wrote:
> 
> I commented out the use of ExcelWriter and instead changed it to wb.save(filename) like you suggested. This fixes the problems with writing to excel, as it now creates excel files without error again.
> 
> However, it looks like the issue with multiple Excel files being created is still present.
> 
> This is a minimal example that reproduces the issue:
> https://gist.github.com/janfreyberg/fece6b94493e66f5d98644fcc9ff9037
> 
> —
> You are receiving this because you were assigned.
> Reply to this email directly, view it on GitHub, or mute the thread.

@janfreyberg I've narrowed this down to a simple bug in `tools.fileerrortools.handleFileCollision()`. Will propose a fix tonight.


Resolving patch:
diff --git a/psychopy/data.py b/psychopy/data.py
--- a/psychopy/data.py
+++ b/psychopy/data.py
@@ -4334,8 +4334,7 @@ def saveAsExcel(self, fileName, matrixOnly=False, appendFile=False,
             label = thisStair.condition['label']
             thisStair.saveAsExcel(
                 fileName, sheetName=label, matrixOnly=matrixOnly,
-                appendFile=append, fileCollisionMethod='rename'
-            )
+                appendFile=append, fileCollisionMethod=fileCollisionMethod)
             append = True
 
     def saveAsText(self, fileName,
diff --git a/psychopy/tools/fileerrortools.py b/psychopy/tools/fileerrortools.py
--- a/psychopy/tools/fileerrortools.py
+++ b/psychopy/tools/fileerrortools.py
@@ -34,10 +34,12 @@ def handleFileCollision(fileName, fileCollisionMethod):
     elif fileCollisionMethod == 'rename':
         rootName, extension = os.path.splitext(fileName)
         matchingFiles = glob.glob("%s*%s" % (rootName, extension))
-        count = len(matchingFiles)
 
         # Build the renamed string.
-        fileName = "%s_%d%s" % (rootName, count, extension)
+        if not matchingFiles:
+            fileName = "%s%s" % (rootName, extension)
+        else:
+            fileName = "%s_%d%s" % (rootName, len(matchingFiles), extension)
 
         # Check to make sure the new fileName hasn't been taken too.
         if os.path.exists(fileName):


Test patch: