Why doesn’t Revit check spelling in schedules? No good reason that I know of, so here’s an investigation into how it might be done with the API. There’s also some discussion of JSON deserialization and communicating with the Bing Spell Check web API.
public void scheduleSpellCheck()
{
Document doc = this.ActiveUIDocument.Document;
ViewSchedule viewSchedule = doc.ActiveView as ViewSchedule;
ViewSheet viewSheet = doc.ActiveView as ViewSheet;
if (viewSchedule == null && viewSheet == null)
{
TaskDialog.Show("Error", "Active a schedule or sheet before running this command");
return;
}
SectionType sectionType = SectionType.Body;
List<string> scheduleText = new List<string>();
List schedules = new List();
if (viewSheet != null)
{
schedules = new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance)).Cast()
.Where(q => q.OwnerViewId == viewSheet.Id)
.Select(q => doc.GetElement(q.ScheduleId) as ViewSchedule)
.Where(q => !q.IsTitleblockRevisionSchedule).ToList();
}
else
{
schedules.Add(viewSchedule);
}
foreach (ViewSchedule vs in schedules)
{
scheduleText.Add(vs.Name);
for (int i = 0; i < getRowColumnCount(vs, sectionType, true); i++)
{
for (int j = 0; j < getRowColumnCount(vs, sectionType, false); j++)
{
try
{
scheduleText.Add(vs.GetCellText(sectionType, i, j));
}
catch (Exception ex)
{
}
}
}
SpellCheck(string.Join(" - ", scheduleText));
}
}
static async void SpellCheck(string text)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
// The following headers are optional, but it is recommended they be treated as required.
// These headers help the service return more accurate results.
//client.DefaultRequestHeaders.Add("X-Search-Location", ClientLocation);
//client.DefaultRequestHeaders.Add("X-MSEdge-ClientID", ClientId);
//client.DefaultRequestHeaders.Add("X-MSEdge-ClientIP", ClientIp);
HttpResponseMessage response = new HttpResponseMessage();
string uri = host + path + params_;
List<KeyValuePair<string, string>> values = new List<KeyValuePair<string, string>>();
values.Add(new KeyValuePair<string, string>("text", text));
using (FormUrlEncodedContent content = new FormUrlEncodedContent(values))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
response = await client.PostAsync(uri, content);
}
string client_id;
IEnumerable<string> header_values = new List<string>();
if (response.Headers.TryGetValues("X-MSEdge-ClientID", out header_values))
{
client_id = header_values.First();
Console.WriteLine("Client ID: " + client_id);
}
string results = await response.Content.ReadAsStringAsync();
TaskDialog.Show("JSON", JsonPrettyPrint(results));
FlaggedTokenList flaggedTokenList = new JavaScriptSerializer().Deserialize(results);
List<string> output = new List<string>();
foreach (FlaggedToken flaggedToken in flaggedTokenList.flaggedTokens)
{
List<string> suggestions = flaggedToken.suggestions.Select(q => q.suggestion.ToString()).ToList();
if (suggestions.Count == 0)
continue;
output.Add(flaggedToken.token + " : " + string.Join(",", suggestions));
}
TaskDialog.Show("output", string.Join(Environment.NewLine, output));
}
static string host = "https://api.cognitive.microsoft.com";
static string path = "/bing/v7.0/spellcheck?";
// For a list of available markets, go to:
// https://docs.microsoft.com/rest/api/cognitiveservices/bing-autosuggest-api-v7-reference#market-codes
static string params_ = "mkt=en-US&mode=proof";
// NOTE: Replace this example key with a valid subscription key.
static string key = "d46d0d618a7343dabe8a4355e9d30187";
class FlaggedTokenList
{
public List flaggedTokens { get; set; }
}
class FlaggedToken
{
public string token { get; set; }
public List suggestions { get; set; }
}
class Suggestion
{
public string suggestion { get; set; }
public double score { get; set; }
}
private int getRowColumnCount(ViewSchedule view, SectionType sectionType, bool countRows)
{
int ctr = 1;
// loop over the columns of the schedule
while (true)
{
try // GetCellText will throw an ArgumentException is the cell does not exist
{
if (countRows)
view.GetCellText(sectionType, ctr, 1);
else
view.GetCellText(sectionType, 1, ctr);
ctr++;
}
catch (Autodesk.Revit.Exceptions.ArgumentException)
{
return ctr;
}
}
}
static string JsonPrettyPrint(string json)
{
if (string.IsNullOrEmpty(json))
{
return string.Empty;
}
json = json.Replace(Environment.NewLine, "").Replace("\t", "");
StringBuilder sb = new StringBuilder();
bool quote = false;
bool ignore = false;
char last = ' ';
int offset = 0;
int indentLength = 3;
foreach (char ch in json)
{
switch (ch)
{
case '"':
if (!ignore) quote = !quote;
break;
case '\\':
if (quote && last != '\\') ignore = true;
break;
}
if (quote)
{
sb.Append(ch);
if (last == '\\' && ignore) ignore = false;
}
else
{
switch (ch)
{
case '{':
case '[':
sb.Append(ch);
sb.Append(Environment.NewLine);
sb.Append(new string(' ', ++offset * indentLength));
break;
case '}':
case ']':
sb.Append(Environment.NewLine);
sb.Append(new string(' ', --offset * indentLength));
sb.Append(ch);
break;
case ',':
sb.Append(ch);
sb.Append(Environment.NewLine);
sb.Append(new string(' ', offset * indentLength));
break;
case ':':
sb.Append(ch);
sb.Append(' ');
break;
default:
if (quote || ch != ' ') sb.Append(ch);
break;
}
}
last = ch;
}
return sb.ToString().Trim();
}
I ran into an error. and are missing from the code. I fix that and a dozen new errors show up including a missing .
I fix that and make sure I have the BING lines:
using System.Net.Http;
using System.Net.Http.Headers;
Which make new errors.
Does adding references these references help?
System.Net.Http
System.Web
System.Web.Extensions
System.Web error – “A namespace cannot directly contain members such as fields or methods (CS0116)”
maybe you are missing a { or }
I played around with this as well as spell checking tags (much more complicated, given you have to get parameters in families) a couple years ago.
I’m glad a real developer is looking at it. I was waaaaay above my abilities.