There are existing posts on SO about related topics, and there are support requests on MSDN that are unsolved/unrepaired. It sounds like the "right way" doesn't work, so I'm wondering there is a workaround.
Let me describe what I perceive to be "the right way" that doesn't work, and maybe you have an alternative path that will work.
I can create an Excel VSTO plugin in Visual Studio, create a custom Ribbon.xml and Ribbon.cs file, and then open multiple workbooks which appear as different windows. Per other SO posts, I can hook into the Application_WindowActivate event and call Invalidate() on my ribbon, forcing a refresh of all the callbacks. The ribbon will reflect the state of the Active Window... and so will every other instance of the ribbon in other windows. As a result, the Ribbon that appears in every window is the same Ribbon. If I have a CheckBox or a Button with a Pressed attribute or anything else stateful, those states will propagate to every open Excel window.
This can be avoided by running Excel with the excel /s parameter which appears to create a new process with its own SDI - but this is not a user-friendly solution.
It looks like what you're supposed to be able to do during an onAction ribbon callback is access the IRibbonControl parameter's Context property, which is supposed to be the correct Excel.Window object. In theory this would present either only the Window you are activating, or would execute for each open Window. And with the correct Context you could execute functions that provide different states back to the Ribbon. And then maybe in one Excel window, you ribbon could have a Pressed Button, and in the other window, an unpressed Button. Except it doesn't work.
When I call Invalidate I get two callbacks (not sure why, the MSDN says it might be a bug) both for the newly activated window, and I execute logic to update the state of active window's ribbon. And then the previous window's ribbon updates the same way.
If this is the way it is, fine. We'll tell our users that they may see some funky Ribbon changes on inactive windows but that it will always be correct on the active window. We can deal with that. But if there is a way around this problem that could make it appear as though the Ribbon had different states on a per-workbook/window basis... that'd be really cool.