0% found this document useful (0 votes)
67 views

Transform Clipboard Contents Between Copy and Paste - CodeProject

Transform Clipboard Contents Between Copy and Paste - CodeProject

Uploaded by

gfgomes
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
67 views

Transform Clipboard Contents Between Copy and Paste - CodeProject

Transform Clipboard Contents Between Copy and Paste - CodeProject

Uploaded by

gfgomes
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

Transform Clipboard Contents Between Copy and Paste


Brad Joss, 6 Mar 2019

Alter your clipboard contents before pasting to automate tasks

Download Transform Clipboard source (with executable) - 599.6 KB


Download Transform Clipboard source only - 373.1 KB

Introduction
This Windows desktop application, while running, monitors your clipboard, and allows you to alter the contents before you paste.
This can be quite powerful, for example, copying a range of data in Excel (unformatted) and then transforming it into a pretty table
to be pasted into an email. Or, splitting a string of numbers and getting a distinct, sorted subset for analysis on paste. One of my
favorites is copying the top row of a SQL result set from MS SQL Server Management Studio, and transforming it into a column list
to make selecting and re-arranging the columns easier. The most powerful one is taking an Excel sheet and transforming it into a
SQL temp table script. All with the push of a button.

Major Update (4.0)


I still use this tool almost every day, both at home and work, and have found some opportunities to improve upon this code. The
updated code has several major changes, including:

Filter/Search: Start typing to filter transformers. Backspace/Delete to clear. Current filter and the count of matches shown in
the upper right corner of the transformer list.

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 1/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

Many New Transformers: Escape XML, Remove HTML Tags, and more. The bigger change is that almost all but a handful of
transformations are now done using the .xml file based transformation, as opposed to being coded in C#. Feel free to use
any of the existing transformations as an example or extend upon them to meet your needs.
Configurable Groups: Moved group name and sort order to a configuration file (Groups.xml). You can add/remove/re-
arrange groups as you see fit. There are still constants (GroupSortOrder. CannedGroups.*) that map to values for
use in coded transformers in case you need them, but they are not required. This removed the notion of "group rank", which
was previously used to group items together. Now, a group's sort order is determined by the order in which it appears in the
Groups.xml file. Items with an unknown group added to the top or bottom of the list based on the app.config setting
UNKNOWN_GROUPS_TO_TOP.
In-Line Unit Testing: Since we can add a new transformer by just dropping a text file in the app folder, it made sense that
we should be able to just drop the unit tests in as well. Now both coded transformers and XML transformers have their unit
tests in line. See any of the Transmogifier XML files for examples, or Sample.xml for more details. To run the tests, run
the application with either the /DEBUG or /TEST startup flag, or run the unit test InLineUnitTestRunAll.

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 2/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

ListBoxTransformerItem.ItemType: There was too much confusion around what each list item was (a section header?, a
horizontal rule?, an actual transformer?, etc.), so that logic is now encapsulated into
ListBoxTransformerItem.ItemType. This made figuring out what to show and hide in the list box much cleaner
when filtering.
Serialization Tools: Broke the Serializer calls into its own class, SerializationTools. Why I did not do this years ago
(or why this is not baked into the .NET framework) -- I am not sure! This is code I will certainly reuse.
Debugging Window: Added a debugging window, visible with the /DEBUG flag. This can be useful for diagnosing issues
with a failed transformation.

XML-based Transformer Updates


All of the remaining changes centered on extending the XML-based transformation feature. Broadly speaking, these are now way
more powerful than before, and almost all of the default transformations are done with just the XML files. Unfortunately, this is a
breaking change from the old XML file format. If you need help converting your old transformations to the new format, feel free to
contact me. See "Transformers\Transmogifiers\Sample.xml" for details on all the options, but an overview of the changes includes:

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 3/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

Specify output case (lower, UPPER, Title, None)


Split by chars, strings or regular expressions.
Find and Replace by string or regular expression, including found regular expression patterns (see
TransmogifierReplaceTest for an example).
Regular expressions now support additional options (like toggling case sensitivity).
Input is always assumed to be a "grid" (rows x columns), where a single string is treated as a single cell in the grid. This
added WAY more flexibility in transforming complex data. You can split rows and columns in different ways, act on the split
cells, and re-assemble them in different ways. See Sample.xml for details.
Canned options to make several operations easier and giving you more flexibility in the transformation process. Including:

When and how to trim text (Per row? Per cell? Etc...). See options:
TRIM_ON_SPLIT_ROW,TRIM_ON_SPLIT_COL, REMOVE_EMPTY_ROWS, REMOVE_EMPTY_CELLS for
more details.
How to deal with different types of line breaks. (Can treat \r, \n and \r\n all the same!) See option:
NORMALIZE_NEW_LINES for more details.
How to deal with different types of spaces. (Can treat Ascii(32) the same as  !) See option:
NORMALIZE_SPACES for more details.
Row based operation like sorting, top and distinct. See options: DISTINCT_ROWS, SORT_ROWS, GRIDIFY
and the property TopRows for more details.
I found working with XML escape sequences challenging, especially for new line and tabs. I have created an option of
USE_COMMON_ESCAPE_CHARS that will pre-process the XML file swapping out \n, \r, \t and \l (custom tag
that maps to Environment.NewLine) with their XML escape sequences. It just made working with the
transformation files easier.

Support for raw XLST transformations. Assuming the input is valid XML, you can just apply an XSLT transformation. An
included sample is used to convert the XML help text generated by Microsoft Visual Studio into HTML. Thanks to Emma
Burrows for Simple XSLT stylesheet for Visual Studio .NET XML Documentation.
Group is inferred based on directory structure, unless explicitly set. It just felt more natural that way.
Transmogifier process is broken into several steps to make working with the code easier. See
Transmogifier.Transform for details.
Two stage sorting. Primary sorting of list items is by group, ordered in the order in which they appear in the Groups.xml file.
If a Rank is specified, it will be used to position items within the group, the finally sorting by name.

Background
Repetitive tasks drive me nuts. After having to alter text to make it fit some need over and over and over again, I finally realized
what I need to do is be able to programmatically alter the text in my clipboard without having to go to some intermediate tool.

For example, without this tool, to send results from SQL Server Management Studio to my co-worker, I would copy the results with
headers, launch MS Excel, paste into Excel, format in Excel, copy from Excel, paste into the email to be sent. That's a lot of busy work
just to display a table of data. Given I was doing that many times a day, I needed a solution! This is that solution.

Conversely, I would regularly get Excel workbooks from users asking me to import/export/explain some piece of data. To get that
into our production database on the other side of the firewall was a pain. The Excel to SQL transformation takes the Excel input and
makes it simple to paste that Excel data into a SQL #Temp table, which I can then use to import or analyze the issue.

After using this tool for several years, and sharing with my co-workers, it seemed a proper time to share with the rest of the world.
Enjoy!

Using the Code


This posting is more about making the tool available for others to enjoy. To use, launch the executable, copy something into your
clipboard, select the transformation(s), apply and paste. That's it! For common transformations that you use every day, you can
create a shortcut macro on your desktop (or quick launch bar) to apply the transformation with a single click. See the About section
of the application for more details.

Exploring the Code


This application is a standard WPF desktop application that, for the most part, is unremarkable. However, if you are interested in
extending the code to meet your own needs, it would be helpful to understand some of the moving parts.
https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 4/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

Overview
The general design is a ViewModel bound WPF application. On startup, we use reflection to find all classes that implement
TextTransformerBase in the currently loaded assembly, we then add those classes to the list of transformers displayed in
the application. On transform, we capture the user's clipboard, and apply the transformations (calling Transform(ref text)
on each selected transformer), then write the result back to the clipboard, finally closing the application.

As with most WPF application, we start in App.xaml.cs, in Application_Startup, we parse the command line to see if we are
running in UI mode (display a list of possible transformations) or command line mode (a canned list of transformers was passed in,
so just transform and exit -- no UI). In either case, the core initialization happens in
TextTransformerBase.AllTransformers, where we parse assemblies looking for transformers, returning them as a
collection. They are then wrapped in ListBoxTransformerItem, which keeps track of selection sort order and other UI
features, finally being added to an ObservableCollection that is rendered into the UI.

On selection of any item, we DoPreview() to display what the output of the transformation will look like. Ultimately, if the user
clicks apply, we basically just do VM.ClipboardText = VM.Transform(); and close the application.

All that said, there is quite a bit of code to make the systray bubble work.

Problem 1: Integrating into Win32 components! This code was entirely grafted from the internet (clipboard-event-c-sharp) thanks
to dbkk!

Problem 2: How to display the bubble for the right amount of time after the transformation, but before the application closes
(removing the bubble and systray icon)? Most of the logic around this is in MainWindowVM.DisplayTransformComplete.
If we pass in delegate function (onDoneHandler), we wire it in to a 3 second timer to be called on done. In most cases, this
basically calls VM.Quit() to shut the app down. In any case, no matter what apply mode we are in, as soon as the "apply" starts,
we hide the main window to make it "look" like the application has shut down while we display the popup bubble.

The remaining code that is noteworthy is really the transformer code. My hope in posting this is that developers take this code and
create their own transformers!

Implementing Custom Transformers


For the most power, it may be easiest to write your own transformers depending on your needs. I did try to write the code so you
can just include another assembly (.dll) below the application root and if it contained a transformer, you could use it. This proved
somewhat problematic when it came to security, and that code is currently commented out
(TextTransformerBase.AllTransformers - #if false section).

There are two basic options to create your own transformers.

Option 1 - Transmogrifier (XML-based Transformers)

On startup, Transmogrifier.GetAllTransmogrifiers parse the application directory (and sub directories) for *.xml
files that contain XML-based (serialized) transformation. See Sample.xml for full details, but the gist is: if your tranformation is not
too complex, then you can just create a Transmogrifier. The biggest advantage being no need to re-compile code, just create the
XML (text) file and include it below the application root. Note that you can also include unit tests in the XML file as well, again
avoiding the need to actually compile code.

Option 2 - Custom .NET Transformers

To create your own custom transformer, create a class that implements the abstract base class TextTransformerBase.
The semantics are petty simple (I hope), where the constructor defines the basics (name, group, description, ...), and then overrides

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 5/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

Transform(ref string str) with your custom code.

Example

public class ToUpper : TextTransformerBase


{
public ToUpper()
: base(
GROUP_SORT_ORDER.STRING_CASE, // Group in which to include this transformer
"To Upper", // Name to display
"Make all characters UPPER case." // Tool tip and Help file text
) { }

override public void Transform(ref string str)


{
str = str.ToUpper();
}
}

There are checks in place to ensure str is never null, so you should just be able to write whatever transformations you desire.

Points of Interest
Disable Preview: While working on this post, I had cause to transform a very large SQL result set (> 100 MB). It was SLOOOOW!
After a little debugging, I realized that the issue was solely with the rendering to the UI. As such, I have added a "Disable Preview"
option that will trigger if it thinks the amount of data in your clipboard is too big.

ClipboardFormat: There are some transformers that return HTML. HTML in the clipboard gets tricky. You have to provide these
index positions of where the pasted HTML lives, which is somewhat cumbersome to compute. If you need to return an HTML result,
I would recommend you use HTMLClipboardHelper.HTMLToClipboardFormattedText to provide the result.

Desktop Shortcuts: I have used this app for years, and I always just create macro shortcuts to it by hand, but that's pretty lame. So
with the help of the internet (create-shortcut-on-desktop-c-sharp) and thanks to Simon Mourier, I was able to wire in a simple
button to do so. See ShortcutHelper.CreateShortcut for the "fun" code.

Event Log: Meaningful, but non-crashing, errors are logged to the Windows Event Log. This can be helpful when debugging XML
Transformer issues when you don't have a debugger attached.

KeyHelper: This class is silly, but I couldn't think of a better way to solve the problem of cherry picking what sets of keys are viable
for a subset of actions.

GroupSortOrder: This seemed a practical solution for a user configurable arbitrarily re-sortable list of items. This is likely code I will
use again in the future in some manner or another.

InLineUnitTest: Given we are really just testing text transformations, the unit testing of that is pretty simple string before/after pair
testing. I think this solution worked out well for this use case and lends quite a bit of durability to custom transformers.

Help: I worked hard to have the help be included in-line in a seamless way, which is why TextTransformerBase has a
HelpText property. The styling and other details are defined in Help.html, which is what is ultimately rendered out to the help
window.

History
6th March, 2019 - (5.0) Bug fixes

Fixed bug in Serializable Dictionary that was preventing some transmogrifiers from working correctly
Added debugging aids to both the serialization processes and transmogrify unit tests
Fixed bug in Strip HTML transformer
Fixed bug in Replace Smart Quote transformer
Breaking Change - Removed "Root" element from serializable dictionary by default. To fix your custom
transmogrifiers, remove the <r> and </r> tags in your XML transmogrifies.
Added some fun on the help page

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 6/7
08/03/2019 Transform Clipboard Contents Between Copy and Paste - CodeProject

5th February, 2019 - Major re-write


26th August, 2016 - (My mother's birthday!) - Initial public posting

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author


Brad Joss
No Biography provided
Software Developer (Senior)
United States

Comments and Discussions


9 messages have been posted for this article Visit https://www.codeproject.com/Articles/1118362/Transform-Clipboard-
Contents-Between-Copy-and-Past to post and view comments on this article, or click here to get a print view with messages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2016 by Brad Joss
Web06 | 2.8.190306.1 | Last Updated 7 Mar 2019 Everything else Copyright © CodeProject, 1999-2019

https://www.codeproject.com/Articles/1118362/Transform-Clipboard-Contents-Between-Copy-and-Past?display=Print 7/7

You might also like