How do I text wrap to next acrofield in iTextSharp? - c#

how do I get text to wrap from one acrofield to the next? I have an adobe pdf doc our client gave us. It has acro fields one atop another (all with the same name). They want the text to wrap from one to another when it reaches the end of the line. All the other examples I see out there do not deal with filling in acro fields that wrap. Please help!
// loop through disabilities and display them
foreach (var disability in formNature.Disabilities)
{
fields.SetField("EVALUATION", disability.PrimaryDisabilityName + "; ");
}
in theory this should loop through all the disabilities they had entered on the web form and display them one after another while text-wrapping when it reaches the end of each line. But instead it only displays one item one the field.

This isn't a complete answer unfortunately.
First, when you call SetField() you are erasing the current contents of the field and replacing it with your new value. When done in a loop only the last value will ever be stored then. What you need to do is loop through each value and concatenate them into one big string.
string buf = '';
foreach (var disability in formNature.Disabilities)
{
buf += disability.PrimaryDisabilityName + "; ";
}
buf = buf.Trim();
Second, the PDF standard to the best of my knowledge does not support chaining of fields for overflow which is what you are looking for. The only way that I know of to accomplish what you are trying is to actually measure the strings and compare them to the widths of the fields and truncate them as needed. To do this you will need to find the font used for the given field, create a BaseFont from it and use that to Measure the string. Then compare that with the field's rectangle and use only the characters that "fit" into that field. Repeat as needed.
That all said, I would really really recommend that you just edit the PDF and replace the multiple fields with one large field that supports multiple lines. Your life will be much, much easier.

Related

Can you read multiple variables on one line with Streamreader()?

I'm working in c# and wondering if it's possible to read back multiple variables and load into an array using Streamreader.Readline()?
Here's an example:
I have an array of different types being written using Streamwriter
foreach (Stuff stf in StuffArray)
{
sw.WriteLine(" " + stf.car+ " " + stf.carOwned + " " + stf.carLocation);
}
sw.Close();
It writes out a text line that looks like:
Magnum True Alabama
When I go to read it back the only option I have is to read the entire line with Streamreader.
I want to load it back like:
for (int i = 0; i < stfArray.Length; i++)
{
stfArray[i] = new stfArray(Readline spot 1, Readline spot 2, Readline spot3)
}
So I can put the stuff back into the array or a new array in the exact same way it was when I extracted it.
Thanks!
Read the line, parse it (say with string.Split) and then take the tokens that you've parse and rehydrate your variables.
You probably want to use a more sophisticated format that word, space, etc. (think of cars whose model name contains a space, or places like New York). Pick a separator that will not occur in your strings.
Or better still, pick a well known serialization format like XML or JSON.
Since you are creating string representation on your own, you are 100% sure about its format. Under any other occasion, you should consider something more robust, like serialization to XML and then writing it to a file.
In your situation I would recommend creating new collection of Stuff and add object, that lies in every line of your file, like:
List<Stuff> stuffItems = new List<Stuff>();
while(!streamReader.EndOfStream)
{
string[] line = streamReader.ReadLine().Split(' ');
stuffItems.Add(new Stuff(line[0], line[1], line[2]));
}
And now you can use this list however you want, for example overwrite old one calling ToArray method on list, etc.
But, again, I warn you about this approach: when you change your format, for example change delimiting character, you'd get exception :)

C# How to get automated number of heading in Word Interop

I have code (as soon below) that loops through all the paragraphs and finds a specific string. When I find the string, I print out the automated number of the header it belongs to. The problem, I want the header number as well and can't figure out how to get it. Code here:
Edit: Cleaned up code with working content
string LastHeader = "";
foreach (Paragraph paragraph in aDoc.Paragraphs)
{
Microsoft.Office.Interop.Word.Style thisStyle =
(paragraph.Range.get_Style() as Microsoft.Office.Interop.Word.Style);
if (thisStyle != null && thisStyle.NameLocal.StartsWith("Heading 2"))
{
LastHeader = paragraph.Range.ListFormat.ListString + " " +
paragraph.Range.Text.Replace("\"", "\"\"").Replace("\r", "");
}
else
{
string content = paragraph.Range.Text;
for (int i = 0; i < textToSearch.Count; i++)
{
if (content.Contains(textToSearch[i]))
{
// Do stuff here
}
}
}
}
Every time I re-read your information I get the feeling I'm not understanding completely what you're asking, so the following may contain more information than you're looking for...
To get the numbering of a specific Paragraph:
paragraph.Range.ListFormat.ListString
Word has some built-in bookmarks that can give you information that is otherwise a lot of work to determine. One of these is \HeadingLevel. This gets the first paragraph formatted with a Heading style that precedes a SELECTION. And that's the sticky part, because we don't really want to be making selections... But it dates back to the old WordBasic days when code mimicked user actions, so we're stuck with that.
textToAnalyse.Select
aDoc.Bookmarks("\HeadingLevel").Range.ListFormat.ListString
The bookmark call, itself, will NOT change the selection.
The other option I see, since you're already looping the Paragraphs collection, would be to check the paragraph.Range.Style and, if it begins with the string "Heading" (assuming that's not used otherwise in these documents' styles) save the ListFormat.ListString so that you can call on it if your condition is met.
I do have to wonder, however, why you're "walking" the paragraphs collection and not using Word's built-in Find capability as that would be much faster. It can search text AND (style) formatting.

Good way to write ID3v2 track number as string in C#?

Forgive me if this question is already answered somewhere on this site, but I didn't find anything when I searched for it. I've written a ID3v1/2 tag editor for .mp3 files in C# using taglib-sharp, and taglib-sharp treats the track numbers as uint numbers. According to id3.org:
The 'Track number/Position in set' frame is a numeric string
containing the order number of the audio-file on its original
recording. This may be extended with a "/" character and a numeric
string containing the total numer of tracks/elements on the original
recording. E.g. "4/9".
Personally I don't use "/", but I tend to write "03" instead of "3". Is there a simple way to write the track number to the tag as a string directly, instead of via a uint?
Also, side question: taglib doesn't seem to support some tags, specifically URL, Orig. Artist, Publisher and Encoded. Any idea on what to do with those?
UPDATE: Since this answer was originally written, GetTextAsString was made public. This answer has been updated to reflect that.
The Track field in TagLib# is a universal approximation and simplification of various tagging specifications intent for the tag field. For ID3v2 tags, this is assuming the TRCK field consists of one or two numbers strings separated by a slash and converting them into numbers, per the specification.
That said, it is a text field and you can do whatever you want with it. You just need to access the text frame to read or write it.
Writing is easy through Id3v2.Tag.SetTextFrame:
var tag = (Id3v2.Tag)file.GetTag(TagTypes.Id3v2, true); // Get or create ID3v2 tag.
tag.SetTextFrame("TRCK", "03"); // Add or update TRCK frame.
Since TRCK is a single-string text frame, it can similarly be read using Id3v2.Tag.GetTextAsString:
var tag = (Id3v2.Tag)file.GetTag(TagTypes.Id3v2, false);
var trackNumber = tag?.GetTextAsString("TRCK");
No you can't save a string into an int or uint without casting it first. Why don't just you save your value 3 as a uint as per the library you are using and use something like:
uint track = 3;
string strTrack = track.ToString("00");
to display it?
If it's allowed by its license, you can still modify the library to suit your needs.
I've taken a quick look at taglib sharp in the past and it's far from supporting all existing frames in a tag. It supports the most common frames only. For the other ones, I think there is some kind of default class you can use but I don't recall the name. Otherwise you can still go and extend the library by yourself unless there are some other such libraries available, which I am not aware of.

C# Saving "X" times into one .txt file without overwriting last string

Well, now i have a new problem.
Im writing code in C#
I want to save from textBoxName into group.txt file each time i enter string into textbox and click on save button. It should save at this order (if its possible to sort it like A-Z that would be great):
1. Petar Milutinovic
2. Ljiljana Milutinovic
3. Stefan Milutinovic
4. ... etc
I cant get it to work, i tried to use tehniques from my first question, and no solution yet :(
This is easy one i guess, but im still a beginer and i need this baddly...
Try to tackle this from a top-down approach. Write out what should happen, because it's not obvious from your question.
Example:
User enters a value in a (single-line?) textbox
User clicks Save
One new line is appended to the end of a file, with the contents of the textbox in step 1
Note: each line is prefixed with a line number, in the form "X. Sample" where X is the line number and Sample is the text from the textbox.
Is the above accurate?
(If you just want to add a line to a text file, see http://msdn.microsoft.com/en-us/library/ms143356.aspx - File.AppendAllText(filename, myTextBox.Text + Environment.NewLine); may be what you want)
Here's a simple little routine you can use to read, sort, and write the file. There are loads of ways this can be done, mine probably isn't even the best. Even now I'm thinking "I could have written that using a FileStream and done the iteration for counting then", but they're micro-optimizations that can be done later if you have performance issues with multi-megabyte files.
public static void AddUserToGroup(string userName)
{
// Read the users from the file
List<string> users = File.ReadAllLines("group.txt").ToList();
// Strip out the index number
users = users.Select(u => u.Substring(u.IndexOf(". ") + 2)).ToList();
users.Add(userName); // Add the new user
users.Sort((x,y) => x.CompareTo(y)); // Sort
// Reallocate the number
for (int i = 0; i < users.Count; i++)
{
users[i] = (i + 1).ToString() + ". " + users[i];
}
// Write to the file again
File.WriteAllLines("group.txt", users);
}
If you need the file to be sorted every time a new line is added, you'll either have to load the file into a list, add the line, and sort it, or use some sort of search (I'd recommend a binary search) to determine where the new line belongs and insert it accordingly. The second approach doesn't have many advantages, though, as you basically have to rewrite the entire file in order to insert a line - it only saves you time in the best case scenario, which occurs when the line to be inserted falls at the end of the file. Additionally, the second method is a bit lighter on the processor, as you aren't attempting to sort every line - for small files however, the difference will be unnoticeable.

C# - Comparing two CSV Files and giving an output

Need a bit of help, I have two sources of information and the information is exported to two different CSV file's by different programs. They are supposed to include the same information, however this is what needs to be checked.
Therefore what I would like to do is as follows:
Take the information from the two files.
Compare
Output any differences and which file the difference was in. (e.g File A Contained this, but File B did not and vice versa).
The files are 200,000 odd rows so will need to be as effective as possible.
Tried doing this with Excel however has proved to be too complicated and I'm really struggling to find a way programatically.
Assuming that the files are really supposed to be identical, right down to text qualifiers, ordering of rows, and number of rows contained in each file, the simplest approach may be to simply iterate through both files together and compare each line.
using (StreamReader f1 = new StreamReader(path1))
using (StreamReader f2 = new StreamReader(path2)) {
var differences = new List<string>();
int lineNumber = 0;
while (!f1.EndOfStream) {
if (f2.EndOfStream) {
differences.Add("Differing number of lines - f2 has less.");
break;
}
lineNumber++;
var line1 = f1.ReadLine();
var line2 = f2.ReadLine();
if (line1 != line2) {
differences.Add(string.Format("Line {0} differs. File 1: {1}, File 2: {2}", lineNumber, line1, line2);
}
}
if (!f2.EndOfStream) {
differences.Add("Differing number of lines - f1 has less.");
}
}
Depending on your answers to the comments on your question, if it doesn't really need to be done with code, you could do worse than download a compare tool, which is likely to more sophisticated.
(Winmerge for example)
OK, for anyone else that googles this and finds this. Here is what my answer was.
I exported the details to a CSV and ordered them numerically when they were exported for ease of use. Once they were exported as two CSV files, I then used a program called Beyond Compare which can be found here. This allows the files to be compared.
At first I used Beyond Compare manually to test what I was exporting was correct etc, however Beyond Compare does have the ability to be able to use command lines to compare. This then results in everything done programatically, all that has to be done is a user views the results in Beyond Compare. You may be able to export them to another CSV, I havn't looked as the GUI of Beyond Compare is very nice and useful, so it is easier to use this.

Categories

Resources