Target and Copy selection from one Excel file to another - C# - c#

Quite some time ago I created a Powershell script to do what I wrote in the title: Copying a selection from File-A to File-B. The way I need it (and the way I did it) is to open a "Template" file when the application starts, the user selects a range, then they have 4 option buttons. The most-used is "Copy Selection", which will copy the contents of the range selection to all of the Excel files in a specific directory. With Powershell this works (although it took a long time to figure out) with the following code:
$strRow = $Excel.ActiveCell.Row
$strColumn = $Excel.ActiveCell.Column
$Range = $sourceWorksheet.Cells.item($strRow,$strColumn)
$Range.Select
$Excel.Selection.Copy() | Out-Null
foreach ($item in $files)
{
$destinationPath = $item.FullName
$destinationWorkBook = $Excel.WorkBooks.Open($destinationPath)
$destinationWorkSheet = $destinationWorkBook.worksheets.item(1)
$destRange = $destinationWorkSheet.Cells.item($strRow,$strColumn)
$destRange.Select
$destRange.PasteSpecial() | Out-Null
$destinationWorkBook.Close($true)
}
That works fine, but I obviously want to get rid of Powershell. I've created a C# application using WPF that will look and work great, I just have to get the logic working. I can't seem to actually target a range selection. I've tried a number of methods and properties, and none seem to get what I need. I can get the actual "selection" cell, but I can't get any type of range. The object I retrieve generally have Rows and Columns properties, so if need-be I guess I could extrapolate that information...but there's gotta be a better way.
Right now the closest thing I have would be to use Application.ActiveCell.Copy(); (or Select), but it seems to have issues when I try pasting it.
Any ideas? I can't seem to figure out why this isn't working.
EDIT: I've solved my own issue...sorry if anyone wasted time looking at this.
I'm an idiot...I spent a bit more time and figured out how to do it. The below code works perfectly - the main issue I was running into is that using Worksheet.Cells.item requires a bracket. I still have to loop through the documents to apply to, but this should take care of the actual logic:
int intRow = myApp.ActiveCell.Row;
int intCol = myApp.ActiveCell.Column;
myApp.Selection.Copy();
Range destRange = mySheet.Cells.Item[intRow,intCol];
destRange.PasteSpecial();
Hope I didn't waste anyone's time and they can figure this out now!

Related

Filter elements in Revit and set parameter

Hello everybody,
around two or three month ago I started to learn Dynamo for Revit... finally :)
After learning and testing a lot, I got a few own scripts working. Then I learned Python, because I couldn't create the next script only with Dynamo-Nodes.
Then I thought "Let's see how difficult it is to get something done as a PlugIn".
I watched some Videos and read a lot of stuff.
Finally I got the Revit-AddIn-Wizard installed and made my first small Test-PlugIn.
Great...
Now I have a few problems which I do not understand... so I thought I will try my luck here... because I got so much information and help, reading through this site.
My goal was/is the following: (I tell you what I have now)
A form with a few buttons, comboboxes and a DataGridView.
I can load an Excelfile, click on "Show" to show it in the DataGridView.
The header of each row will be automatically put into 3 comboboxes.
In the first combobox you select the first search-parameter, in the second you CAN select another search-parameter and in the third combobox you select the parameter you want to set.
I have a checkbox to switch from type- to instance-parameter for the search- and the set-operation.
There is also a button which shows another small form with a list of categories (I won't search for ALL, only nearly all modelcategories).
PlugIn
I took me a lot of "watching Videos, reading through the internet, testing, testing and testing".
Thanks to this site here and a few others... I managed to get this whole PlugIn nearly 100% working.
But now I have a few strange issues and I have absolutely no clue on how to fix them or if it is possible. And I really hope that someone can help me.
First... I just tell you my problems and perhaps someone can say "this really IS an issue!" or that it is possible to get it done. Then I would post some code.
So... what do I do?!
1. I have a FilteredElementCollector which filters ALL elements.
2. Depending on my "Type/Instance-Checkboxes" I do .WhereElementIsElementType OR .WhereElementIsNotElementType.
3. Then it passes a MultiCategoryFilter to get the big list down to only the modelcategories.
4. Next, the collection passes one of ten different "methods" depending on all settings. There I filter this collection depending on the searchlists-comboboxes. When the combobox says "Familie" or "Typ" then it filters for ".BuiltInParameter.SymbolFamilyName" or ".Name" otherwise it just uses ".LookupParameter".
After that I have a collection with only the elements of selected categories which contains the values from the Excellist.
5. Depending on what my search- and set-settings are (e.g. search for type and set instance) I have to get the instances from the collected types or the other way around.
6. Then I pass it down to another method where I finally set the parameter.
So... Excelheader goes into comboboxes, depending on what you select in there it creates lists with the values of the selected rows.
I hope you all understand.
Now... where are my problems?
When I search for type-familynames or instance-parameter and set a typeparameter it works for ALL categories without any error.
1. When I try to set an instanceparameter (doesn't matter what my search-setting are) it works for all "normal" families but not for the systemfamilies (e.g. walls, floors, pipes etc.). No error, just nothing happens WHY? It seems that I cannot set an instance-parameter for system-families.
2. Roofs, Stairs, CurtainPanels and GenericModel make problems when I search for a typeparameter Error is something like "The object reference was not set to an object instance". Only with these 4 categories and it doesn't matter what I want to set... but when I search for family-/typeNAME or Instance-Parameter, then I can set type or instance and it works (except instance for sysfam).
3. When I try to search AND set an instance-parameter it works for ALL categories EXCEPT if one wall does not contain a search value... it really is enough that ONE wall does not have a search-param-value that everything will be cancelled.
I have a few other small problems... but I hope someone can help me with these problems... I would be extremely thankfull
greetings and have a nice day or night :)
Philipp
Tl; dr.
The three problems you describe sound like your own. I have no heard anybody else runAsk three separate questions and provide three separate minimal code snippets describing how they arise,. into those. I suggest that you create three separate independent minimal reproducible cases to demonstrate all three issues. Chances are, when you simplify and minimalise your code, the problem will go away. If it does not, it might just possibly be in a small and manageable enough state for other people to help you take a look at it. Given the long-winded description above, nobody in the world can help you.
Thank you for your answer Jeremy,
as I said, as a first start it is ok for me if you don't say "With theses categories, there are indeed some issues!"
I think I've managed to create 3 small examples of my problems.
For each problem I made a zip-file containing the complete visual-studio folder, a small exampleproject and a readme.txt with (I hope) enough information to understand everything in detail.
Problem1
Problem3
You only need to compile them or copy the .addin and .ddl files into the Revit AddIn folder. Then you get the new ribbons.
Short problem summary = I get problems when searching for parametervalues and setting values to another parameter.
Edit: I just solved the 2. problem when searching for familynames and setting system-families-parameter.
I used:
ElementClassFilter ecf = new ElementClassFilter(typeof(FamilyInstance));
FilteredElementColletor colle2 = new FilteredElementCollector(doc);
colle2.WherePasses(ecf);
I simply deleted the ClassFilter and do it now like in the other cases where I need instances.
FilteredElementCollector colle2 = new FilteredElementCollector(doc);
colle2.WhereElementIsNotElementType();
The 1. and 3. problem still exist :/
I would be thankful for any help someone can provide :)

Excel-DNA: grouping rows via C API feature of Excel-DNA

I'm familiar with how to group a range in Excel VSTO/COM interop:
ws.EnableOutlining = true;
ws.Outline.SummaryRow = XlSummaryRow.xlSummaryAbove;
var rng = GetRangeSomeHow();
rng.EntireRow.Group();
rng.EntireRow.OutlineLevel = someLevel;
What is the most efficient way to do this in Excel-DNA? I would imagine there must be a C-API way to do it, encapsulated cleverly in Excel-DNA somehow, but for the life of me, I can't figure it out via online documentation (incl. Google).
There's a lot of posts using code similar to my sample above, but these are pretty expensive calls, especially since I need to do this ~5000 times overall (I have a really big data set).
EDIT:
So there seems to be this method call:
XlCall.Excel(XlCall.xlfGroup...)
The only problem is, I have no idea what the parameters are. It seems an ExcelReference should be passed in, but how is the .EntireRow resolved? Will the C API just handle it for me - in which case I just need to pass a new ExcelReference(1,100,1,1) and be done with it... or is there more to this?
Thanks in advance to anyone who can answer my question!
I don't think the C API GROUP function is te one you're looking for. The documentation says:
GROUP
Creates a single object from several selected objects and returns the
object identifier of the group (for example, "Group 5"). Use GROUP to
combine a number of objects so that you can move or resize them
together.
If no object is selected, only one object is selected, or a group is
already selected, GROUP returns the #VALUE! error value and interrupts
the macro.
I'd suggest you use the COM object model for this kind of thing, even in an Excel-DNA add-in. The C API has not really been updated over the years for the general sheet manipulation like this case, so you're likely to run into some features that don't work right or are incomplete relative to the COM object model.
From your Excel-DNA add-in, just make sure your get hold of the right Application root object with a call to ExcelDnaUtil.Application.
For improved performance of this kind of sheet editing, you pretty much have to use the same tricks as from VBA or VSTO - disable screen updating and calculations etc.

InlineShapes disappear when the layout of a chart in Word is changed. Where do they go?

I've been developing a Word-AddIn (Office 365 version 1706, Windows 10) which basically stores data in charts so they could be fed updated data from our servelets and ultimately the chart updates itself with all the data it needs.
This works perfectly fine EXCEPT when I alter the layout options for a chart from the default "In Line with Text" to "With Text Wrapping" to have multiple charts next to each other for example.
How this works, as long as you don't alter the layout options, is by accessing the Microsoft.Office.Interop.Word.Application COM object, which has a Selection object, which furthermore has InlineShapes, is like so:
var inlineShapes = Application.Selection.InlineShapes;
if(inlineShapes > 0)
{
for(var i = 1; i < inlineShapes.Count + 1; i++)
{
if (inlShape.HasChart == MsoTriState.msoTrue)
return new WordChart(inlShape);
}
}
For sake of simplicity I spared you the whole ordeal of dealing with COM objects.
Again, this works if you don't tamper with the layout options of the chart, but as soon as the layout has been altered to say "Behind Text" I can't find that chart in any InlineShape.
Has anyone experienced this before?
I've combed through the Application.Selection object and couldn't find anything.
However the InlineShape is still in the Application.InlineShapes object itself, but how would I know which one is to be selected?
I would really appreciate ANY input, because as of now I have no idea on what to do anymore.
Ok, I finally found those little charts!
This Stackoverflow post helped me:
How to check which shapes/objects are selected/active?
More details to what solved my problem:
Once I changed the the layout options (see original question) I wouldn't be able to find Charts as InlineShapes anymore.
Instead they would be listed under Selection.ShapeRange.get_Item(i) (I checked for Shapes/InlineShapes, so I didn't see items as what a chart could be).
Now you could either convert them to InlineShapes, which does exactly that, in Word as well, which you don't want, or convert that Shape to your VSTO.WordChart, which I did.

Getting a resource in Xamarin

I am trying to do something very basic: Have an ImageButton load an image and an associated sound and have that sound play. I thought it would be easy to do, but I'm having two problems (although it probably is two symptoms of the same problem).
One, I don't see the images I added to the Resources/drawable folder show up in the Resource.Drawable class, all I see there is the default Icon from icon.png. I added 20 images with a .jpg extension and set them to AndroidResource in properties. They were numerically named, so I modified them to start with a letter (in case that was the problem), got rid of a dot in the name (in case that was the problem), and finally renamed them to .jpeg (in case that was it). These don't seem to be reasons why they don't show up.
The Resource.Designer.cs works, though, because the two mp3s I added to the Resources/raw do show up in the class.
The other problem I have is that I can't tell how to load them programatically, so I can pass them to
imageButton.SetImageResource(imageId);
I tried
var imageId = this.Resources.GetIdentifier("DigiBord.Sunete:i00011", null, null);
which didn't work, but maybe the items were not in the project. So I tried again with an item I knew was in the project:
var imageId = this.Resources.GetIdentifier("DigiBord.Sunete:Icon", null, null);
which again yielded 0. There must be a way to load them without knowing the int id of the item ahead of time.

VS2010: Automatically insert date and initials to single line comments

Greetings Friends,
What is the best way (least amount of keystrokes) to get Visual Studio 2010 to automatically insert the current date and my name/initials whenever I put a single line comment into my codebase? This should support C# and it'd be even better if it worked in my .aspx pages too.
Thanks -- I know someone out there has the perfect solution :).
Create a macro and assign a Shortcut key.
The easiest way is go to Tools->Macros->Macro Explorer and edit one of the samples, I used Samples->VSEditor, right click that one and edit.
Now youre in the Macro editor
Now create this function.
Sub NewCommentLinePersonal()
Dim textSelection As EnvDTE.TextSelection
textSelection = DTE.ActiveWindow.Selection
textSelection.NewLine()
textSelection.Insert(Utilities.LineOrientedCommentStart())
textSelection.Insert(" " + Date.Now + " - Your Initial ")
End Sub
then go to Tools->Options->Environment->Keyboard and type the NewCommentLinePersonal on textbox "Show commands containing:" then choose your shortcut key
Perhaps another way of approaching it, assuming the insertion of a timestamp and name is being done for change tracking, is to lean on source control.
For example, in my current codebase, we deprecated the use of putting in change comments, since we found that the field of green was cluttering things, and if I ever needed to see who changed what, I could simply look in our source control system, and even see how this one change was related to other modifications within the same changeset.

Categories