I'd like to search through the tree in CATIA, and return the names of the parts in the tree using C#. My current code is as follows:
private void Search(object sender, EventArgs e)
{
string searchName = OriginalBox.Text;
string name;
INFITF.SelectedElement part;
//CATIA.StartCommand("Search");
try
{
Sel.Search("Name=" + searchName + "*, all");
for (int i = 1; i <= Sel.Count; i++)
{
part = Sel.Item(i);
name = part.get_Name();
MessageBox.Show(i.ToString() + " : " + name);
}
}
catch (IOException ex)
{
if (ex.Source != null)
MessageBox.Show(ex.Source);
throw;
}
}
The MessageBox displays "CATIASelectedElement45". I am receiving the message "ERROR HRESULT E_FAIL has been returned from a call to a COM component." when assigning the Sel.Item(i) to part.
How can I access the part name using Selection.Search?
On Sel.Search("Name=" + searchName + "*, all"); you are searching for any object containing that name, if you would like to search exclusively for Part only, you should use a type search:
Sel.Search("(((((('Product Structure'.Part + FreeStyle.Part) + 'Assembly Design'.Part) + 'Part Design'.Part) + 'Generative Shape Design'.Part) + 'Functional Molded Part'.Part) + 'Process Applications'.Part);all");
//To get any search string, use search on Catia and copy it from there.
Also, to get the real value from selection inside your For use this:
Sel.Item(i).Value; // Object retrieved from selection
name = ((INFITF.AnyObject) Sel.Item(i).Value).get_Name(); // Object Name
Note that the SelectedElement class is just a middle class to abstract all kinds of objects into a selection. It contains some properties and methods that may be usefull sometimes though, such as Reference and LeafProduct.
Then instead of using Selection search I think it is ideal to loop through a specific type of feature like Bodies, Hybridbodies, Shapes..etc
While looping through it you can compare the item name value with your string value and store it.
Something like this:
int bodiesCount = Part.Bodies.count
for (int i = 1; i <= bodiesCount; i++)
{
string name = Part.Bodies.Item(i).Name;
if(name == TextBox.Text("your string value"))
{
Sel.Add(Part.Bodies.Item(i));
MessageBox.Show(i.ToString() + " : " + name);
}
}
You can try this:
Sel.Search ("Name=" + searchName + "* & CATPrtSearch,all");
for (int i = 1; i <= Sel.Count; i++)
{
MECMOD.Part selectedPart;
selectedPart = Sel.Item(i).Value;
name = selectedPart.get_Name();
MessageBox.Show(i.ToString() + " : " + name);
}
Related
I have created a code to create folders with two Textboxes.
Textbox1 - customer number (XXXX).
Textbox2 - customer name.
I would like to be able to check if the customer number exists before creating the folder.
The newly created folder will be the combination of the two Textboxes (this is already solved).
I just need to be able to determine if the folder exists only with the customer number, as it is probably created with (customer number + customer name).
Current working code:
{
string no = textBox1.Text;
string client = textBox2.Text;
string carpeta = #"C:\" + no + " " + client;
string sourcePath = #"C:\main";
string destinationPath = #"C:\" + no + " " + client;
textBox1.Clear();
textBox2.Clear();
try
{
if (Directory.Exists(carpeta))
{
DialogResult y;
y = MessageBox.Show("Folder already exists\nDo you want to open it?", "AE.", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (y == DialogResult.Yes)
{
System.Diagnostics.Process.Start(#"C:\" + no + " " + client);
}
else
{
Close();
}
}
else
{
DialogResult x;
x = MessageBox.Show("The folder doesn't exist\nWant to create a folder?." + "\n" + no + " " + client, "AE.", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (x == DialogResult.Yes)
{
Directory.CreateDirectory(carpeta);
FileSystem.CopyDirectory(sourcePath, destinationPath, UIOption.AllDialogs);
System.Diagnostics.Process.Start(#"C:\" + no + " " + client);
}
else
{
Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error:" + ex.Message);
}
}
You could also each time you need the folder just do that:
public static void Main()
{
var username = "someuser";
var usernumber = "ABC123";
var mainDirectory = #"C:\Path\To\The\Main\Dir";
var pathToTheUserDirectory = Path.Combine(mainDirectory, $"{username}-{usernumber}");
// This line will create the directory if not exist or take the existing directory.
var directoryInfo = Directory.CreateDirectory(pathToTheUserDirectory);
var directoryPath = directoryInfo.FullName;
// ...
// or
// directoryInfo.Delete(recursive: true);
}
string[] dirs = Directory.GetDirectories(#"c:\", txtTextBox.Text + "*");
this will only get directrories starting with the desired Text
Edit: This is only a good solution if the customer number has fixed places (in you exaple 4 from 0000-9999)
Microsoft Documentation - check example below
As i'm trying to web scrape a part from the website. Here is an image below.
as the pagination is checked in red box i need to extract value of last in the image above it is 151. So the pagination is dynamic which is hard to extract when i check using view page source in only <div class="jsx-46358917 pagination-wrapper text-center"></div> is shown as inside its value is missing as i understand it is dynamic but i need the last value from the pagination example 151.
Here is a code which i have done so far to web scrape it.
public void parseItem(HtmlDocument doc, string zipCode)
{
//Getting json data
if (doc.DocumentNode.LastChild.HasChildNodes)
{
var siteScripts = doc.DocumentNode.SelectSingleNode("//script[#id='__NEXT_DATA__']").InnerText;
var result = JsonConvert.DeserializeObject<RealtorModel>(siteScripts);
if (result != null)
{
foreach (var realtor in result.Props.CriteriaData.SrpShell.LoadedData.SearchResults.HomeSearch.Results)
{
string propertyId = "M" + realtor.PropertyId;
string address = realtor.Location.Address.Line + ", " + realtor.Location.Address.City + ", " + realtor.Location.Address.StateCode + " " + realtor.Location.Address.PostalCode;
string listingURL = hostName + "/realestateandhomes-detail/" + realtor.Permalink;
var url = realtor.PrimaryPhoto;
listings.Add(new Listings { PropertyID = propertyId, Address = address, Price = realtor.ListPrice, ImageURL = realtor.PrimaryPhoto.Href.AbsoluteUri, ListingURL = listingURL });
}
}
pageNumber = pageNumber + 1;
string nextUrl = "https://www.realtor.com/realestateandhomes-search/" + zipCode + "/type-single-family-home" + "/pg-" + pageNumber;
AddTask(nextUrl, this.parseItem, zipCode);
}
else
{
System.Threading.Thread.Sleep(60000);
string nextUrl = "https://www.realtor.com/realestateandhomes-search/" + zipCode + "/type-single-family-home" + "/pg-" + pageNumber;
AddTask(nextUrl, this.parseItem, zipCode);
}
}
As i get the complete page through scraping only thing is the last value of the paginate which i cannot extract due to its dynamic nature. How can i achieve to do so any hint would be helpful.
I have a simple Windows Forms application with a form that has two TextBoxes to find postcode/suburb name:
Enter the suburb name
Enter the postcode
If the postcode (TextBox) has no value entered the form is hung up and it won't submit/return values. Tried a few things but still fails (FormatException was unhandled). Adding any int value it works fine.
private void btnFind_Click(object sender, EventArgs e)
{
//DECLARE ARRAY
string[] arrSuburbName = new string[5];
int[] arrSuburbPC = new int[5];
//POPULATESUBURB NAME ARRAY
arrSuburbName[0] = "DEE WHY";
arrSuburbName[1] = "SYDNEY";
arrSuburbName[2] = "HURSTVILLE";
arrSuburbName[3] = "BALMAIN";
arrSuburbName[4] = "NORTH SYDNEY";
//POPULATE POSTCODE ID ARRAY
arrSuburbPC[0] = 2099;
arrSuburbPC[1] = 2000;
arrSuburbPC[2] = 2220;
arrSuburbPC[3] = 2041;
arrSuburbPC[4] = 2060;
//VARIABLES
string inputSuburb = "";
int inputPostCode = 0;
string msg = "";
//INPUT
inputSuburb = txtInputSuburb.Text.Trim();
inputPostCode = int.Parse(txtInputPostCode.Text);
//PROCESS
for (int i = 0; i < arrSuburbPC.Length; i++)
{
if (inputSuburb.ToUpper() == arrSuburbName[i])
{
msg = "Postcode for " + arrSuburbName[i] + " is: " + arrSuburbPC[i];
inputPostCode = 0;
break; //EXIT THE LOOP
}
else if (inputPostCode == arrSuburbPC[i])
{
msg = "Postcode for " + arrSuburbName[i] + " is: " + arrSuburbPC[i];
break; //EXIT THE LOOP
}
else
{
msg = "Postcode Not Found";
}
}
//OUTPUT
lblResult.Text = msg;
}
Why don't you use Int.TryParse(...) instead of Int.Parse(...)?
Parse v. TryParse
You have
inputSuburb = txtInputSuburb.Text.Trim();
inputPostCode = int.Parse(txtInputPostCode.Text);
but in the UI screen you attached you gave OR so it can happen that postcode will be empty.
You need to change you logic in code. Things to consider:
What to do if post code is empty? -> this is your situation right now
What if user enter non-number like 'abcd'
Your logic should have some validation. Use try catch construction for example.
Maybe you should also consider user NumericUpDown control?
I want to filter dates range. I'm using the dynamic LINQ library. I have to build my where string into a variable based on several factors and then pass the string variable to the where clause.
In my ASP.NET MVC project I wrote a helper.
private string GetFilterCondition(string filterCondition, string filterDataField, string filterValue)
{
switch (filterCondition)
{
case "CONTAINS":
return " " + filterDataField + ".Contains(\"" + filterValue + "\")";
case "GREATER_THAN_OR_EQUAL":
return " " + filterDataField + " >= " +"\"" + filterValue + "\"";
case "LESS_THAN_OR_EQUAL":
return " " + filterDataField + " <= " + "\"" + filterValue + "\"";
}
return "";
}
And I used parameter in query which I've passed from the ASP.NET MVC project;
public int GetFilteredCount(string searchValue)
{
var filteredRecords = 0;
try
{
var query = DB.Categories.AsQueryable();
var totalRecords = query.Count();
if (!string.IsNullOrEmpty(searchValue))
{
searchValue = searchValue.Trim();
query = query.Where(searchValue);
}
filteredRecords = query.Count();
}
catch (Exception e){}
finally
{
DestroyDbContext();
}
return result;
}
When filtering date range ("GREATER_THAN_OR_EQUAL", "LESS_THAN_OR_EQUAL"), I get an error:
Operator '>=' incompatible with operand types 'DateTime' and 'String'
Please note, that with 'contains' works.
I uploaded picture to see what looks like searchvalue parameter
I rewrote GetFilterCondition function like this:
case "GREATER_THAN_OR_EQUAL":
return string.Format(" {0} >= DateTime.Parse(\"{1}\")", filterDataField, filterValue);
case "LESS_THAN_OR_EQUAL":
return string.Format(" {0} <= DateTime.Parse(\"{1}\")", filterDataField, filterValue);
after executed filteredRecords = query.Count() throws this error:
LINQ to Entities does not recognize the method 'System.DateTime Parse(System.String)' method, and this method cannot be translated into a store expression
I am currently modifying an existing application, I am removing the old UI elements and replacing them with standard WinForms components. So this code is functional as it appears.
My code is passing the conditional IF check when it should not be. The text for each of the comboboxes is <Any> by default, so they should skip past the encapsulated code.
(When filters are selected, they replace the default text to select the correct parts of SQL query to return results)
Now for the bizarre part!
The text property is coming up as System.Data.DataRowView for some of my combobox.text. Originally, this happened for all of them but now the first check appears as <Any> as intended. (Although I didn't change anything at all)
As you can see in this screenshot of my code during debug. The pinned value of cbRegGroup.Text is System.Data.DataRowView but when I enter the list of properties and scroll down to the text property it is shown as <Any>.
I have cleaned and rebuilt my project... and consulted with a college but neither of us can work out why text value is appearing like a .ToString()'ed object.
I am at a loss at what to do next. Any suggestions?
private void LoadPupilView()
{
try
{
this.Cursor = Cursors.WaitCursor;
dgMain.Rows.Clear();
//now populate list view
String filter = "[surname] LIKE '" + SearchString + "%'";
if (!cbYearGroup.Text.Equals("<Any>"))
{
String YearGroupCode = null;
try
{
YearGroupCode = cbYearGroup.SelectedValue.ToString();
}
catch { }
if (!String.IsNullOrEmpty(YearGroupCode))
filter = filter + " AND [yearGroup] LIKE '" + YearGroupCode + "'";
}
if (!cbRegGroup.Text.Equals("<Any>"))
{
String RegGroupCode = null;
try
{
RegGroupCode = cbRegGroup.SelectedValue.ToString();
}
catch { }
if (!String.IsNullOrEmpty(RegGroupCode))
filter = filter + " AND [registrationGroup] LIKE '" + RegGroupCode + "'";
}
if (!cbHouse.Text.Equals("<Any>"))
{
String HouseGroupCode = null;
try
{
HouseGroupCode = cbHouse.SelectedValue.ToString();
}
catch { }
if (!String.IsNullOrEmpty(HouseGroupCode))
filter = filter + " AND [houseGroup] LIKE '" + HouseGroupCode + "'";
}
DataRow[] dataRows = tblPupils.Select(filter);
foreach (DataRow datarow in dataRows)
{
dgMain.Rows.Add(new object[] {
datarow[0].ToString(),
datarow[1].ToString() + " " + datarow[2].ToString(),
datarow[5].ToString(),
datarow[4].ToString(),
datarow[6].ToString(),
datarow[3].ToString()
});
}
}
catch (Exception err)
{
MessageBox.Show("Error : " + err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
this.Cursor = Cursors.Default;
}
}
I'm very interested in knowing why this seems to be inconsistent... why is the first conditional check passed? When the rest aren't although they are the same.
You need to set the DisplayMember property of the ComboBox to the name of the column you want to display.