Building equal number of records list object
Try following some simple rules: Avoid setting flags in loops. Try calculating the data you need before taking action. Only increment counters inside loop declaration. This way even if something gets broken - you will not have to wonder "how did we end up here?". Instead you will be able to tell "this index / limit is not calculated correctly".

Also when saying 


  even if that means that first column doesn't fill page to bottom on the second page


Did you mean:


  even if that means both columns don't fill the last page to the bottom


This is how I understood it.

int ROWS_PER_PAGE = 41;
int totalDataCount = dataTable.Rows.Count;
int pagesToProcess = (int)Math.Ceiling(totalDataCount / 2.0 / ROWS_PER_PAGE);
int itemsPerPage = ROWS_PER_PAGE * 2;

for(int pageIdx = 0; pageIdx &lt; pagesToProcess; pageIdx++)
{
    int itemsOnThisPage = (pageIdx + 1) * itemsPerPage &gt;= totalDataCount ? totalDataCount - pageIdx * itemsPerPage : itemsPerPage;
    int rowsOnThisPage = (int)Math.Ceiling( itemsOnThisPage / 2.0 );
    for( int rowIdx = 0; rowIdx &lt; rowsOnThisPage; rowIdx++)
    {
        var item = new DataForExcelExport();
        int itemIdx1 = pageIdx * itemsPerPage + rowIdx;
        int itemIdx2 = itemIdx1 + rowsOnThisPage;
        SetItemData(dataTable.Rows[itemIdx1], item, true);
        if(totalDataCount &gt; itemIdx2)
            SetItemData(dataTable.Rows[itemIdx2], item, false);
    }
}


Ah yes, and try to name variables in a meaningful way. Names like i or maxrow do not tell what the variable is really used for.