Changing data before exporting excel - c#

I have a list which contains boolean values. I want to export that list to excel, but it must be meaningful for the customer. When I export it as it is, it shows values like True and False as expected, but these values might probably have no meaning in the perception of the customer. This is the way I do the excel export:
LiveModReports model = new LiveModReports();
List<ModerationDM.DetailedContent> liveModListDM = new List<ModerationDM.DetailedContent>();
liveModListDM = contentBLL.GetContentsForMod(modId, startDate, endDate);
if (liveModListDM != null)
{
model.ContentExcelList = new List<ContentExcel>();
foreach (var item in liveModListDM)
{
model.ContentExcelList.Add(new ContentExcel()
{
ModerasyonNumarasi = item.ModId,
Kategori = item.Category,
AltKategori = item.SubCategory,
IcerikAdresi = item.ContentURL,
IcerikSahibiTamAdi = item.ContentUFullName,
IcerikSahibiEPosta = item.ContentUserEmail,
IcerikMetni = item.ContentText,
Durumu = item.ResultCode,
SonDegistirilmeTarihi = (DateTime)item.ModifiedTime,
ModerasyonKategorisi = item.ModCategoryName,
IcerikNumarasi = item.ContentSeqNum,
BegeniPuani = item.LikeCount,
BegenilmemePuani = item.DislikeCount,
PaneldenVerilmisCevapMi = item.IsAnswer,
CevaplanmisMi = item.IsAnswered,
RaporlamaBasligi = item.ReportHeader
});
}
}
CreateExcelFile.CreateExcelDocument(model.ContentExcelList, "IcerikListesi.xlsx", System.Web.HttpContext.Current.Response);
For example, IsAnswer must be shown as "Evet" which means "Yes" in Turkish, but it's shown as "True" now. How can I change the values before they're written to excel?

You are the one preparing the model before writing it to Excel. Thus, you can simply change the properties to fit your needs.
Examples like
PaneldenVerilmisCevapMi = (item.IsAnswer) ? "Evet" : "No"
would work for you but you can do anything with these objects. Such as - passing it to a method that changes things like True to Evet or anything else that will look beter for an end user.
MakeDataReadable(model.ContentExcelList);

Use the ternary operator in order to be more meaningful with your data, for example:
PaneldenVerilmisCevapMi = (item.IsAnswer ? "Yes" : "No"),
...
Explain: if IsAnswers evaluates to true, use "Yes", otherwise, use "No".
Note that PaneldenVerilmisCevapMi must be a string.
UPDATE:
if item.IsAnswer is a nullable type, change your if statement to:
PaneldenVerilmisCevapMi = (item.IsAnswer.HasValue ? "Yes" : "No"),

You could simply write this:
PaneldenVerilmisCevapMi = (item.IsAnswer) ? "Evet" : "No"

Related

How do I create and manipulate a Table property for an IFC object using Xbim?

I am working off of the basic example for amending data (https://github.com/xBimTeam/XbimEssentials). The only thing I'm changing is within the code below, where I want to add an IfcPropertyTableValue instead of an IfcPropertySingleValue.
This code runs, but in XbimXplorer under the object's properties, nothing's there - it's blank.
To make sure, the example code, as well as other property types do work and do show up in Xplorer under properties.
var pSetRel = model.Instances.New<IfcRelDefinesByProperties>(r =>
{
r.GlobalId = Guid.NewGuid();
r.RelatingPropertyDefinition = model.Instances.New<IfcPropertySet>(pSet =>
{
pSet.Name = "Points";
// FOR EACH POINT i :
pSet.HasProperties.Add(model.Instances.New<IfcPropertyTableValue>(p =>
{
p.Name = "Points " + i;
// FOR EACH COORDINATE x :
p.DefiningValues.Add(new IfcText(x));
p.DefinedValues.Add(new IfcReal(-3.25));
}));
});
});
How can I make this work?
I have also tried using code to read the property, in case XbimXplorer just doesn't display tables. This code runs and prints zero lines (but works for other properties that are displayed in Xplorer):
// Try to read and print the new property
var nameObj = "my_object_name";
var checkObj = model.Instances.FirstOrDefault<IIfcBuildingElement>(d => d.Name == nameObj);
if (checkObj == null)
{
outputBox.AppendText(newLine + "Object: " + nameObj + " not found");
}
else
{
var properties = checkObj.IsDefinedBy
.Where(r => r.RelatingPropertyDefinition is IIfcPropertySet)
.SelectMany(r => ((IIfcPropertySet)r.RelatingPropertyDefinition).HasProperties)
.OfType<IIfcPropertySingleValue>();
foreach (var property in properties)
outputBox.AppendText($"Property: {property.Name}, Value: {property.NominalValue}");
}
It would also be convenient if I could add several defining/defined value pairs at once, for instance like this (similar to normal C# lists):
IEnumerable<IfcValue> definingValues = new IfcText() {"x", "y", "z", "k"};
p.DefinedValues.AddRange(definingValues);
IEnumerable<IfcValue> definedValues = new IfcReal() {0.0, 1.6, -2.5, 3.33};
p.DefinedValues.AddRange(definedValues);
However, {"x", "y", "z", "k"} is then marked with the error Cannot initialize type 'IfcText' with a collection initializer because it does not implement 'System.Collections.IEnumerable'.
I don't think xbim Xplorer displays IfcPropertyTableValues. Probably because very few BIM tools currently output TableValues so I guess it never got implemented (and you'd need to establish how to display the table in the Xplorer view - do you nest a table in a property grid?).
If you look at the Xplorer code you'll see it only supports SingleValues, ComplexValues and EnumeratedValues. You might be able to use Complex Values as a collection of multiple IfcPropertySingleValues as a workaround.
In your 2nd code sample to output the values, you're filtering out any IfcPropertyTableValues with the .OfType<IIfcPropertySingleValue>() clause so you'll never see the output. Take a look at the IFC specs for SimpleProperties: https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/link/ifcsimpleproperty.htm
On the last question you're initializing the array with the wrong syntax. Try something like this:
var labels = new Ifc4.MeasureResource.IfcText[] { "x", "y" };
p.DefiningValues.AddRange(labels.Cast<IIfcValue>());

While trying to add the value i.e. American express to the vendor field, the code is not working

List<ListOrRecordRef> List = new List<ListOrRecordRef>();
ListOrRecordRef RecordRefItem = new ListOrRecordRef();
RecordRefItem.name = "American Express";
RecordRefItem.internalId = "898";
RecordRefItem.typeId = "394";
List.Add(RecordRefItem);
rec.customFieldList = List.ToArray();
WriteResponse response = service.add(rec);
The code is used to add multiselect option of vendor. ex : american express
First of all like Heinz Siahaan said: 'List' is a keyword in C# so you can't create variable with this name.
Second:
ListOrRecordRef RecordRefItem = new ListOrRecordRef();
I'm not sure but name of this method suggest that this line of code creates list of records not one item so you can't use something like this:
RecordRefItem.name = "American Express";
but you should try :
RecordRefItem[i].name = "American Express";
where i is and index of element, but before access it you must create it
found a way its working fine://Note that for multi select option to set we have to take two class:ListOrRecordRef mention the id of the 898:American express&
//SelectCustomFieldRef to mention the field
ListOrRecordRef recordRefItem = new ListOrRecordRef();
recordRefItem.internalId = "898";
SelectCustomFieldRef scfr = new SelectCustomFieldRef();
scfr.scriptId = "custrecord_from_so_customer";
scfr.value = recordRefItem;//set the object value to the mentioned field
customFieldArray[1] = scfr;
rec.customFieldList = customFieldArray

How to assign different enums to a variable in C#

I'm trying to do something like this..
enum Birds {
Crow,
Sparrow,
Hawk
}
enum Bugs {
Ant,
Spider,
Scorpion
}
if (featherless == true) {
var beast = Bugs;
} else {
var beast = Birds;
}
string a = (beast)2.ToString();
I have five lines of code that works on the provided enum. I can't imagine that I have to duplicate these five lines.. something like the above must be able to be used... The above structure of course causes beast to be out of scope and I can't pass var as a parameter. I know this is a headsmack moment, but I've searched and can't find a similar question.
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var a = Enum.GetValues(beastType).GetValue(2).ToString();
Will assign Hawk if featherless is true or Scorpion if it's false.
Edit 0
Maybe this will be a better solution if you only need the name:
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var a = Enum.GetName(beastType, 2);
Edit 1
Maybe you can try this if you need an object for further operations:
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var beast = Enum.ToObject(beastType, 2);
var a = beast.ToString();

Include properties based on conditions in anonymous types

Supposing I have the following anonymous type
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = r.ArriveTime,
TimeOut = r.LeaveTime,
});
Is it possible to do something like the following:
var g = records.Select(r => new
{
Id = r.CardholderNo,
if (condition)
{
TimeIn = r.ArriveTime;
},
TimeOut = r.LeaveTime,
//many more properties that I'd like to be dependant on conditions.
});
How can I achieve an anonymous type based on conditions?
You can do this by using the ternary operator: ?:
The syntax is like this:
TimeIn = condition ? r.ArriveTime : (DateTime?)null // Or DateTime.Min or whatever value you want to use as default
UPDATE
After thinking about your problem for a couple of minutes I came up with the following code that you should never ever use ;)
using System;
class Program
{
static void Main(string[] args)
{
DateTime dt = DateTime.Now;
bool condition = true;
dynamic result = condition ?
(object)new
{
id = 1,
prop = dt
}
:
(object)new
{
id = 2,
};
Console.WriteLine(result.id);
if (condition) Console.WriteLine(result.prop);
}
}
This code should never be used in production because of it's terrible readability and it's really error prone. However, as a learning example of what's possible with the language it's quite nice.
Not directly using an if statement, but you could do it using the ternary operator (assuming TimeIn is of type DateTime):
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = condition ? r.ArriveTime : (DateTime?)null;
TimeOut = r.LeaveTime
});
Note this will make the property always appear in your Annonymous Type. If this isn't the desired behavior, then you can't do it this way.
I would suggest thinking about the readability of your code and not only about "how can i shorten these few lines so it looks neat".
No. Anonymous types are just like any other type. It has a fixed list of properties. You can't dynamically add or remove properties.
I suggest to either set the property to null, like in the other answers, or use a Dictionary where you add the relevant properties and their values.
If you really need an if (or any another statement) in your Anonymous Type creation, you can try this not-so-pretty solution:
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = new Func<DateTime?, DateTime?>(x =>
{
if (...)
return x;
else
return null;
}).Invoke(r.ArriveTime),
TimeOut = r.LeaveTime,
});

How much do conditionals affect performance?

How much do conditionals effect performance? For example, would code A execute faster than code B since it is only checking the boolean value once? (data is a DataTable in this example)
Code A:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
if(isBusiness) {
var name = data["businessName"];
var id = data["businessId"];
var phone = data["businessPhone"];
var address = data["businessAddress"];
}
else {
var name = data["customerName"];
var id = data["customerId"];
var phone = data["customerPhone"];
var address = data["customerAddress"];
}
Code B:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
var name = isBusiness ? data["businessName"] : data["customerName"];
var id = isBusiness ? data["businessId"] : data["customerId"];
var phone = isBusiness ? data["businessPhone"] : data["customerPhone"];
var address = isBusiness ? data["businessAddress"] : data["customerAddress"];
This is a small example so the actual difference would be small, but what if I were mapping hundreds of rows like this? Some care about the isBusiness flag and some don't. Does anyone have any statistical evidence one way or the other?
I don't think there is a clear answer for this question. It depends on how many rows etc, the only one who can answer it is you. To test it you can simply use the Stopwatch class.
I don't think there will be many/any difference, so I would say A, since it is more readable/editable.
I agree with other responders here; however, I would like to add to this.
The performance hit incurred by if statements is something to be taken into consideration if a given method will be run often. If you would like to learn more about the specifics of this effecting performance, I recommend reading this post about conditional branching.
That being said, I will say that you get a pretty much Insignificant Performance Boost by changing the first line of code from this:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
to this:
bool isBusiness = !string.IsNullOrEmpty(data["businessName");
Though, out of the two options I prefer the first one
The reason for this, is that if you would like to push for some code clarity, you could refactor it from this:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
if(isBusiness) {
var name = data["businessName"];
var id = data["businessId"];
var phone = data["businessPhone"];
var address = data["businessAddress"];
}
else {
var name = data["customerName"];
var id = data["customerId"];
var phone = data["customerPhone"];
var address = data["customerAddress"];
}
to this:
bool isBusiness = !string.IsNullOrEmpty(data["businessName");
if(isBusiness) {
this.MapBusinessRow(data);
}
else {
this.MapCustomerRow(data)
}
Though, I must say, that is purely for readability and is not for performance.
At the end of the day, if you are worried about it; Test It!

Categories