Following the steps from this post, I have used the following code to modify just one custom property from a .xslm file (excel with macros):
var newProp = new CustomDocumentProperty();
newProp.VTInt32 = new VTInt32("1");
newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
newProp.Name = "CurrentVersionExported";
using (var document = SpreadsheetDocument.Open(excelPath, true))
{
var props = document.CustomFilePropertiesPart.Properties;
var prop = props.Where(p => ((CustomDocumentProperty)p).Name.Value == "CurrentVersionExported").FirstOrDefault();
// If the property exists, get the return value and then delete the property.
if (prop != null)
{
prop.Remove();
}
// Append the new property, and fix up all the property ID values.
props.AppendChild(newProp);
int pid = 2;
foreach (CustomDocumentProperty item in props)
{
item.PropertyId = pid++;
}
props.Save();
}
It works well but there are two things that I do not understand:
What is the pid? i believe it is the property ID, but I do not understand why it has to be 2 initially.
How should I know the initial format ID from my property? My excel does not have an XML schema so I have used the format ID from the post I linked before, I do not know if it is wrong or not to use that one.
Related
I'm sending a JSON object through PUT from angularJS to c#, which has a property name and a value.
I'm trying to loop for each property and read both name and the value, but it fails. I have succeed to read only the name or only the value though with the below code:
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (string pricegroupInfo in cbpcs.Properties().Select(p => p.Value).ToList())
{
// I want to be able to do something like this inside here
if(pricegroupInfo.Value == "Something") {
// do stuff
}
}
In my above example pricegroupInfo has the value, if i change .Select(p => p.Name).ToList()) i get the name of the property.
What can I do if i want to get both name and value inside my loop ?
Update 1: The property Name is unknown to me, it's generated dynamically so I dont know in advance the property name.
Update 2: I want to be able to compare the value and the name as a string inside the loop.
Try using an anonymous object in the select.
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (var pricegroupInfo in cbpcs.Properties().Select(p => new { p.Value, p.Name }).ToList())
{
// read the properties like this
var value = pricegroupInfo.Value;
var name = pricegroupInfo.Name;
if(pricegroupInfo.Value.ToObject<string>() == "foo")
{
Console.WriteLine("this is true");
}
}
Reference: JObject.Properties Method
Newtonsoft.Json.Linq.JObject cbpcs = pricestopsale.cbPricegroups;
foreach (var pricegroupInfo in cbpcs.Properties())
{
if(pricegroupInfo.Name == "propName" // your property name
&& pricegroupInfo.Value.ToString() == "something") { // your value
// do stuff
}
}
As you can see, it returns IEnumerable<JProperty> which use can iterate and make use of to get property Name and Value
Try this
foreach(var prop in cbpcs.GetType().GetProperties()) {
Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(foo, null));}
I have the following tree in EPI CMS:
[Root]
.
.
--[Lobby] ID=1
--Foo1
--Foo2
--Foo3
--[ContainerOfSubFoo] ID=2
--SubFoo1
--SubFoo2
--SubFoo3
I want when I edit Foo1, to have check boxes of all the SubFoo's.
What I have now is this:
private static List<SelectItem> GetSubFoos()
{
PageReference pRef = new PageReference(2); //(ID=2 is my container page - ContainerOfSubFoo)
PageData root = DataFactory.Instance.GetPage(pRef);
var pages = DataFactory.Instance.GetChildren<Models.Pages.SubFoo>(root.ContentLink);
List<SelectItem> targetsList = new List<SelectItem>();
foreach (var target in pages)
{
targetsList.Add(new SelectItem() { Value = target.ContentLink.ID.ToString(), Text = target.SubFooProperty });
}
return targetsList;
}
This works fine but I don't want to use ID=2, I want the GetSubFoos to go "up" (to Lobby) then go "down" to the first ContainerOfSubFoo and get all the children of SubFooType
The GetSubFoo method is on the Foo class
I can provide the code of the SelectionFactory if needed.
Another problem I see now is that the checkbox "V" does not save :/
(the string is saved with the values comma seperated but the checkboxes
are all unchecked
this was solved by adding .ToString() for the ID
From within the selection factory, you can obtain the current content via a handy extension method EPiServer.Cms.Shell.Extensions.FindOwnerContent() on the ExtendedMetadata that is passed in by EPiServer:
public virtual IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
var selections = new List<SelectItem>();
var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
var ownerContent = metadata.FindOwnerContent();
if (ownerContent is Foo)
{
var containerRoot = contentRepository.GetChildren<ContainerOfSubFoo>(ownerContent.ParentLink).FirstOrDefault();
var pageOptions = contentRepository.GetChildren<SubFoo>(containerRoot.ContentLink);
foreach (var target in pageOptions)
{
selections.Add(new SelectItem() { Value = target.ContentLink.ID.ToString(), Text = target.SubFooProperty });
}
}
return selections;
}
You can then traverse the page tree to find what you need.
I am working with a system which allows users to add C.V.s to a company database. A document consists of sections and for each section there can be one or more fields. A field corresponds to a user control which is mapped to a specific field type. The user controls are not bound to the document object in any way and to save data to the document from the page containing the user controls there is a method like this:
public void SaveData(Document document)
{
// Get all user controls on the page
var userControls = FindDescendants<UserControl>(this);
foreach (var section in document.Sections)
{
foreach (var field in section.Fields)
{
if (field is Address)
{
var address = field as Address;
var addressControl = userControls.FirstOrDefault(o => o.ClientID.Contains(field.Id)) as AddressUserControl;
addressControl.SaveData(address);
}
else if (field is TelephoneNumbers)
{
var telephoneNumbers = field as TelephoneNumbers;
var telephoneNumbersControl = userControls.FirstOrDefault(o => o.ClientID.Contains(field.Id)) as TelephoneNumbersUserControl;
telephoneNumbersControl.SaveData(telephoneNumbers);
}
...
...
else if (field is Employment)
{
var employment = field as Employment;
var employmentControl = userControls.FirstOrDefault(o => o.ClientID.Contains(field.Id)) as EmploymentUserControl;
employmentControl.SaveData(employment);
}
}
}
}
I do not like the nested loops and each time a new field type is added the conditional statement within the foreach grows.
Any ideas how this could be structured more elegantly?
I'm using C# MVC to connect to NetSuite using their WebServices API. I have some current code that calls a saved search of inventory items. Here is the current code that is working perfectly:
ItemSearchAdvanced searchItems = new ItemSearchAdvanced();
searchItems.savedSearchId = "128";
SearchResult result = netSuiteSvc.search(searchItems);
int totalRecords = 0;
int processedRecords = 0;
UpdateNetsuitePriceListModel returnObj = new UpdateNetsuitePriceListModel();
returnObj.NewPriceList = new List<NetSuitePriceListRecord>();
if (result.status.isSuccess)
{
SearchRow[] searchRows = result.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
for (int i = 0; i < searchRows.Length - 1; i++)
{
ItemSearchRow itemRow = (ItemSearchRow)searchRows[i];
if (itemRow.basic.itemId != null && itemRow.basic.mpn != null && itemRow.basic.basePrice != null && itemRow.basic.salesDescription != null)
{
returnObj.NewPriceList.Add(new NetSuitePriceListRecord()
{
ItemId = itemRow.basic.itemId[0].searchValue,
ManufacturerPartNumber = itemRow.basic.mpn[0].searchValue,
ContractPrice = Convert.ToDecimal(itemRow.basic.basePrice[0].searchValue),
Cost = CalculateProductCostForIngram(Convert.ToDecimal(itemRow.basic.basePrice[0].searchValue)),
Description = itemRow.basic.salesDescription[0].searchValue
});
processedRecords++;
}
totalRecords++;
}
}
else
{
throw new Exception("NetSuite Part List Blank");
}
}
else
{
throw new Exception("NetSuite Part List Search Failure");
}
Now I have need to pull the itemId from a custom added field rather than the default itemId field.
Obviously since this is a custom field it isn't a property of ItemSearchRowBasic. It looks like instead of the property I can choose "customFieldList" which is an array of "SearchColumnCustomField". If I choose an index for the array I can see that SearchColumnCustomField contains:
customLabel
internalId
scriptId
I imagine I should be able to get the internalId of the SearchColumnCustomField and somehow use that to get the search value for that custom column but I've had some trouble finding any examples that fit so far.
This custom field is a free form text field added to all inventory items.
Try setting scriptId with the ID of the field ("custitem_xyz"). That should work.
Before 2013 one would use internalId, but since then it changed to scriptId.
You would need to loop over the CustomRecord items in the customFieldList. I then usually check for a specific type so I can cast to the correct object, but with some reflection you could probably avoid that.
foreach (Record r in mySearchResponse.recordList){
foreach (CustomFieldRef cr in ((CustomRecord)r).customFieldList){
if (cr.GetType().Name == "SelectCustomFieldRef"){
if (((SelectCustomFieldRef)cr).scriptId == "my_custom_field"){
internalID = ((CustomRecord)r).internalId;
}
}
}
}
I'm writing an function to update a row in table (SQLite). At one time I only need to update certain columns of that row.
My Video class (and table) has these properties (and columns):
Id, Name, Lyric, Cover,Gendre, Url. ( they're all string)
Now, for example, I need to update the lyric and cover of 1 row in table , I'm using this code:
string id = // still keep the old id, this's the PK of table;
string lyric = //get new lyric;
string cover = // get new cover;
Video item = new Video(){Id = id, Lyric = lyric, Cover = cover};
SQLiteAccess.EditVideoInfo(item);
Here's the EditVideoInfo
public static void EditVideoInfo(Video item)
{
var conn = new SQLiteConnection(mypath);
using (conn)
{
var list = conn.Query<Video>("SELECT * FROM Video WHERE Id =?", item.Id);
if (list.Count >0)
{
var editItem = list.First(); // -> Get the item need to updated
/// Here's where I'm stuck
conn.Update(editItem);
}
}
}
So how can I read "foreach" each property of the new item and update to the old item's property if that property isn't null ?
Something like below.
var props = typeof(Video).GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.GetProperty|BindingFlags.SetProperty);
foreach (var prop in props) {
var propVal = prop.GetValue(item, null);
if (propVal != null)
prop.SetValue(editItem, propVal, null);
}
You can use reflection to get all the properties of the Video item (take a look at http://msdn.microsoft.com/en-us/library/kyaxdd3x(v=vs.110).aspx) but the solution would be slow and messy. Just write the test and update code for each property.
My first approach to do this is to create a dictionary
Dictionary<string, string> _properties = new Dictionary<string, string>();
_properties["id"] = "myID"
_properties["lyric"] = "some other string"
and then you can iterate through it with a foreach
foreach (var prop in _properties)
{
// do something with prop
}