Skip to content

Commit

Permalink
BatchRvtGUI / BatchRvt: add support for Excel files as Revit File Lis…
Browse files Browse the repository at this point in the history
…t (if Excel is installed on the system)
  • Loading branch information
DanRumery committed May 1, 2018
1 parent ac41e66 commit 4b06e04
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 5 deletions.
73 changes: 73 additions & 0 deletions BatchRvt/Scripts/excel_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,47 @@
xlNoChange = 1


def FindFirstValue(range, searchOrder, searchDirection):
afterCell = range.Cells[
range.Rows.Count if (searchDirection == Excel.XlSearchDirection.xlNext) else 1,
range.Columns.Count if (searchDirection == Excel.XlSearchDirection.xlNext) else 1
]
return range.Find(
"*",
afterCell,
Excel.XlFindLookIn.xlValues,
MissingValue,
searchOrder,
searchDirection,
MissingValue,
MissingValue,
MissingValue
)

# Returns the row number of the first non-blank row in the range.
# If all rows are blank, returns 0.
def GetFirstUsedRowNumber(range):
firstUsedCell = FindFirstValue(range, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext)
return firstUsedCell.Row if (firstUsedCell is not None) else 0

# Returns the column number of the first non-blank column in the range.
# If all columns are blank, returns 0.
def GetFirstUsedColumnNumber(range):
firstUsedCell = FindFirstValue(range, Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext)
return firstUsedCell.Column if (firstUsedCell is not None) else 0

# Returns the row number of the last non-blank row in the range.
# If all rows are blank, returns 0.
def GetLastUsedRowNumber(range):
lastUsedCell = FindFirstValue(range, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlPrevious)
return lastUsedCell.Row if (lastUsedCell is not None) else 0

# Returns the column number of the last non-blank column in the range.
# If all columns are blank, returns 0.
def GetLastUsedColumnNumber(range):
lastUsedCell = FindFirstValue(range, Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlPrevious)
return lastUsedCell.Column if (lastUsedCell is not None) else 0

def WriteRowsToWorksheet(worksheet, rows):
for rowIndex, row in enumerate(rows):
excelRow = worksheet.Rows[rowIndex + 1]
Expand All @@ -58,6 +99,30 @@ def GetNumberOfRowsAndColumns(worksheet):
usedRange.Column + usedRange.Columns.Count - 1
)

def GetWorksheetRange(worksheet, firstRowNumber, firstColumnNumber, lastRowNumber, lastColumnNumber):
return worksheet.Range[
worksheet.Cells[firstRowNumber, firstColumnNumber],
worksheet.Cells[lastRowNumber, lastColumnNumber]
]

def ReadRowsText(range):
rows = []
for excelRow in range.Rows:
row = []
for excelCell in excelRow.Cells:
row.Add(excelCell.Text)
rows.Add(row)
return rows

def ReadRowsTextFromWorksheet(worksheet):
rows = []
usedRange = worksheet.UsedRange
lastUsedRowNumber = GetLastUsedRowNumber(usedRange)
lastUsedColumnNumber = GetLastUsedColumnNumber(usedRange)
if (lastUsedRowNumber != 0 and lastUsedColumnNumber != 0):
rows = ReadRowsText(GetWorksheetRange(worksheet, 1, 1, lastUsedRowNumber, lastUsedColumnNumber))
return rows

def WithExcelApp(excelAppAction):
result = None
app = Excel.ApplicationClass()
Expand Down Expand Up @@ -105,3 +170,11 @@ def excelAppAction(app):
result = WithExcelApp(excelAppAction)
return result

def ReadRowsTextFromWorkbook(excelFilePath):
def excelWorkbookAction(workbook):
worksheet = workbook.Worksheets[1]
rows = ReadRowsTextFromWorksheet(worksheet)
return rows
rows = WithExcelWorkbook(excelFilePath, excelWorkbookAction)
return rows

17 changes: 17 additions & 0 deletions BatchRvt/Scripts/revit_file_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ def FromLines(lines):
rows = text_file_util.GetRowsFromLines(lines)
return GetCentralFileListFromRows(rows)

def IsExcelInstalled():
return System.Type.GetTypeFromProgID("Excel.Application") is not None

def HasExcelFileExtension(filePath):
return any(path_util.HasFileExtension(filePath, extension) for extension in [".xlsx", ".xls"])

def FromExcelFile(excelFilePath):
centralFilePaths = []
if IsExcelInstalled():
import excel_util
centralFilePaths = GetCentralFileListFromRows(excel_util.ReadRowsTextFromWorkbook(excelFilePath))
else:
raise Exception("ERROR: An Excel installation was not detected! Support for Excel files requires an Excel installation.")
return centralFilePaths

def FromConsole():
return FromLines(console_util.ReadLines())

Expand Down Expand Up @@ -88,6 +103,8 @@ def GetRevitFileList(settingsFilePath):
revitFileList = None
if text_file_util.HasTextFileExtension(settingsFilePath):
revitFileList = FromTextFile(settingsFilePath)
elif HasExcelFileExtension(settingsFilePath):
revitFileList = FromExcelFile(settingsFilePath)
return revitFileList

REVIT_VERSION_TEXT_PREFIXES_2015 = ["Autodesk Revit 2015", "Autodesk Revit Architecture 2015"]
Expand Down
8 changes: 4 additions & 4 deletions BatchRvtGUI/BatchRvtGuiForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion BatchRvtGUI/BatchRvtGuiForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,27 @@ private bool LoadSettings(string filePath = null)

this.UIConfiguration.UpdateUI();

VerifyExcelInstallation(this.revitFileListTextBox.Text);

return isLoaded;
}

private void VerifyExcelInstallation(string filePath)
{
if (!string.IsNullOrWhiteSpace(filePath))
{
if (ExcelUtil.HasExcelExtension(filePath) && !ExcelUtil.IsExcelInstalled())
{
MessageBox.Show(
"WARNING: An Excel installation was not detected! Support for Excel files requires an Excel installation.",
this.Text,
MessageBoxButtons.OK,
MessageBoxIcon.Warning
);
}
}
}

private bool SaveSettings(string filePath = null)
{
this.UIConfiguration.UpdateConfig();
Expand Down Expand Up @@ -615,7 +633,7 @@ private void browseRevitFileListButton_Click(object sender, EventArgs e)
var openFileDialog = new OpenFileDialog();

openFileDialog.DefaultExt = ".txt";
openFileDialog.Filter = "Text files (*.txt)|*.txt";
openFileDialog.Filter = "Revit File List (*.txt;*.xls;*.xlsx)|*.txt;*.xls;*.xlsx";
openFileDialog.CheckFileExists = true;
openFileDialog.ReadOnlyChecked = true;
openFileDialog.Multiselect = false;
Expand All @@ -637,6 +655,8 @@ private void browseRevitFileListButton_Click(object sender, EventArgs e)
if (!string.IsNullOrWhiteSpace(selectedFilePath))
{
this.revitFileListTextBox.Text = selectedFilePath;

VerifyExcelInstallation(selectedFilePath);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions BatchRvtUtil/BatchRvtUtil.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Compile Include="BatchRvt.cs" />
<Compile Include="CommandLineUtil.cs" />
<Compile Include="CommandSettings.cs" />
<Compile Include="ExcelUtil.cs" />
<Compile Include="JsonUtil.cs" />
<Compile Include="LogFile.cs" />
<Compile Include="Network.cs" />
Expand Down
41 changes: 41 additions & 0 deletions BatchRvtUtil/ExcelUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Revit Batch Processor
//
// Copyright (c) 2017 Daniel Rumery, BVN
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace BatchRvtUtil
{
public static class ExcelUtil
{
public static bool IsExcelInstalled()
{
return Type.GetTypeFromProgID("Excel.Application") != null;
}

public static bool HasExcelExtension(string filePath)
{
var extension = Path.GetExtension(filePath).ToLower();

return new[] { ".xls", ".xlsx" }.Any(excelExtension => extension == excelExtension.ToLower());
}
}
}

0 comments on commit 4b06e04

Please sign in to comment.