I have created a wrapper class to access PDF FORMS using PDFBox , by using the wrapper I m trying to execute it with VBScript..
Here is my wrapper class (Class Library) with COM enabled
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.util;
using org.apache.pdfbox.pdmodel.interactive.form;
namespace PDF.API
{
public class PDFDocument
{
private PDDocument PD;
public void load(string PDFPath)
{
PD = PDDocument.load(PDFPath);
}
public PDDocumentCatalog getDocumentCatalog()
{
return PD.getDocumentCatalog();
}
public void save(string PDF_Path)
{
PD.save(PDF_Path);
}
public void close()
{
PD.close();
}
}
here is my vbscript
Set TestPDF = CreateObject("PDF.API.PDFDocument")
Set test = PDFDocument.load("D:\\PDF_FORMS\\sample_form.pdf")
Set PDDocumentCatalog = test.getDocumentCatalog()
Set PDAcroForm = PDDocumentCatalog.getAcroForm()
Set PDFField = PDAcroForm.getField("Forenames")
PDField.setValue("VBSCRIPT")
test.save("D:\\PDF_FORMS\\a.pdf")
test.close()
Now it throws me Object required for PDDocument
could not able to resolve this issue
can any one help me out please
Thanks
As Ansgar Wiechers and Aphoria already mention, your Load is a method of your PDFDocument class, and to simplify yourself, you may use the same name as variable name in your .vbs, i.e.:
Set PDFDocument = CreateObject("PDF.API.PDFDocument")
Next issue I see, is that your Load method is a void (not return value), so the syntax should been like this:
PDFDocument.load "D:\path\to\file_a.pdf"
Set PDDocumentCatalog = PDFDocument.getDocumentCatalog()
' ... '
PDFDocument.save "D:\path\to\file_b.pdf"
PDFDocument.close
And I not touched C# recently, but as far as I remember you need a Constructor.
namespace PDF.API
{
public class PDFDocument
{
private PDDocument PD;
public PDFDocument()
{ //class constructor
}
public void load(string PDFPath)
{
PD = PDDocument.load(PDFPath);
}
// ...
}
}
I think you need to change PDFDocument.load... to TestPDF.load....
Set TestPDF = CreateObject("PDF.API.PDFDocument")
Set test = TestPDF.load("D:\\PDF_FORMS\\sample_form.pdf")
Set TestPDF = CreateObject("PDF.API.PDFDocument")
Set test = PDDocument.load("D:\\PDF_FORMS\\sample_form.pdf")
You're using PDDocument without instantiating it first. You probably meant to do this:
Set test = TestPDF.load("D:\\PDF_FORMS\\sample_form.pdf")
As a side note: I'd recommend to escape backslashes inside your class. In VBScript it's usually not required to escape backslashes in paths (WMI notwithstanding), so it may confuse your users if you handle this differently.
Related
This question already has answers here:
Why abstract class and interface cannot be instantiated?
(2 answers)
Closed 6 years ago.
So I've been struggling on this project for almost a week now and I need help. See I'm trying to have my main program read from three files: MyFileReader, MyCSVReader and MyMorgReader.
On my main program I was trying to create a new simulator along with a new MorgReader that can read from a text file and translate that text file into a simulator based on the text file.
This is what I wrote in the main file of my program:
Program.cs:
class Program
{
static void Main(string[] args)
{
...
...
Simulator sim = new Simulator(Morg1, Morg2, Morg3, Morg4);
MorgReader mr = new MorgReader(new MyCSVReader(new FileReader("C:\\Users\\miiwo\\Dropbox\\Morg.txt")));
Morg m;
while (m = mr.ReadMorg() != null)
{
sim.Add(m);
}
sim.run();
But three things are not working: the line beginning with MorgReader mr, the while loop, and the Add function within the loop. The first problem generates a CS0144 code which is "Cannot create an instance of the abstract class or interface 'MorgReader', and I'm guess that the last two problems are because of the first one, I'm not sure.
My MorgReader is an abstract class and not an interface. But I have attempted to create another class based on my MorgReader abstract class and then generate a new MorgReader from there. But more errors were generated in my attempt.
I work with four files: Program, MyFileReader.cs, MyCSVReader.cs, and MyMorgReader.cs. Maybe the source of the problem could be in anyone of these files I'm not sure. Don't worry, they're not too much, except for Program.cs, which I'm only posting a portion of it for the sake of time.
MyFileReader.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace homework3
{
//*FILE READER CLASS*//
class FileReader : MorgReader
{
//Member Variables
private StreamReader streamReader;
//FileReader function
public FileReader(string fileName)
{
streamReader = System.IO.File.OpenText(fileName);
if (streamReader == null)
throw new Exception("OpenRead() failed for file " + fileName);
}
//Read function
public override string Read()
{
System.IO.StreamReader myFile = new System.IO.StreamReader("C:\\Users\\miiwo\\Dropbox\\Morg.txt");
string myString = myFile.ReadLine();
return streamReader.ReadLine();
}
//Close function
public override void Close()
{
streamReader.Close();
}
}
//*end of MyFileReader class*//
}
MyCSVReader.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace homework3
{
//*MY CSV READER CLASS*//
class MyCSVReader: ReaderDecorator
{
//Member Variables
string[] buf;
char[] delimiterSplit = { ',' };
char[] delimiterAbsorbs = { ' ' };
int index;
//My Csv Reader base
public MyCSVReader(MorgReader wrapped) : base(wrapped)
{
}
//Read Function
protected override string ReadImpl()
{
if (buf == null)
{
String line = Wrapped.Read();
buf = line.Split(delimiterSplit);
index = 0;
}
return buf[index++];
}
//Close Function
public override void Close()
{
WrappedReader.Close();
}
}
//*end of CSV class*//
}
MyMorgReader.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace homework3
{
//*MY MORG READER CLASS*//
abstract class MorgReader
{
//Member Variables
public abstract string Read();
abstract public void Close();
}
//*end of morg reader class*//
//*MY READER DECORATOR CLASS*//
abstract class ReaderDecorator : MorgReader
{
//Member Variables
protected abstract string ReadImpl();
private MorgReader WrapDecorator;
protected ReaderDecorator(MorgReader wrapped)
{
WrapDecorator = wrapped;
}
//WrappedReader function
protected MorgReader WrappedReader
{ get { return WrapDecorator; } }
//Read function
public override string Read()
{
var wrapped = WrappedReader.Read();
if (!string.IsNullOrEmpty(wrapped))
{ wrapped += ","; }
return wrapped + ReadImpl();
}
//Wrapped function
protected MorgReader Wrapped
{
get { return WrapDecorator; }
}
}
//*end of My Reader Decorator Class*//
}
Please let me know if you need more info on my problem. I'll be happy to oblige. I just want to get rid of this error once and for all.
Thank you in advance.
To understand why this is not working you need to better understand what the compiler it trying to tell you with the error message.
Consider this line of your code found in the Program.cs file:
MorgReader mr = new MorgReader(new MyCSVReader(new FileReader("C:\\Users\\miiwo\\Dropbox\\Morg.txt")));
Now I assume that line is producing this compiler error message:
CS0144 code which is
"Cannot create an instance of the abstract class or interface 'MorgReader'"
If you then look at the definition of the MorgReader class you can see it is defined as abstract:
abstract class MorgReader
{
//Member Variables
public abstract string Read();
public abstract void Close(); // I cleaned this line for you
}
Now lets assume the compiler was wrong and it accepted this code as valid:
MorgReader mr = new MorgReader(new MyCSVReader(new FileReader("C:\\Users\\miiwo\\Dropbox\\Morg.txt")));
mr.Read();
mr.Close();
In the code above where would the code for Read and Close methods be defined?
In other words what code would be run when you called those methods?
The answer is the code for those methods is not defined and hence the reason the compiler does not allow you to construct an abstract class.
Edit: But that line also looks wrong for other reasons as you don't define a constructor for the MorgReader that takes a MyCSVReader object.
Please remove the abstract keyword from ReaderDecorator class and use it with a main programme to initiate readers , because you can not initiate abstract class with a new keyword.
MorgReader mr = new ReaderDecorator (new MyCSVReader(new FileReader("C:\\Users\\miiwo\\Dropbox\\Morg.txt")));
I want get the method name from inside itself. This can be done using reflection as shown below. But, I want to get that without using reflection
System.Reflection.MethodBase.GetCurrentMethod().Name
Sample code
public void myMethod()
{
string methodName = // I want to get "myMethod" to here without using reflection.
}
From C# 5 onwards you can get the compiler to fill it in for you, like this:
using System.Runtime.CompilerServices;
public static class Helpers
{
public static string GetCallerName([CallerMemberName] string caller = null)
{
return caller;
}
}
In MyMethod:
public static void MyMethod()
{
...
string name = Helpers.GetCallerName(); // Now name=="MyMethod"
...
}
Note that you can use this wrongly by passing in a value explicitly:
string notMyName = Helpers.GetCallerName("foo"); // Now notMyName=="foo"
In C# 6, there's also nameof:
public static void MyMethod()
{
...
string name = nameof(MyMethod);
...
}
That doesn't guarantee that you're using the same name as the method name, though - if you use nameof(SomeOtherMethod) it will have a value of "SomeOtherMethod" of course. But if you get it right, then refactor the name of MyMethod to something else, any half-decent refactoring tool will change your use of nameof as well.
As you said that you don't want to do using reflection then You can use System.Diagnostics to get method name like below:
using System.Diagnostics;
public void myMethod()
{
StackTrace stackTrace = new StackTrace();
// get calling method name
string methodName = stackTrace.GetFrame(0).GetMethod().Name;
}
Note : Reflection is far faster than stack trace method.
I am developing Add-in for Excel 2013 and I have created a function in Excel Add-In as below
public string ExcelReturnString()
{
return "This is the string: hi";
}
I have used below code to call the function, but it throws an error.
Application.Run(ExcelReturnString)
How can I call the Add-in function in macro?
This is about the farthest thing from straight-forward, but this is how you accomplish the task. I'm going to be as explicit as possible, because the first two or three times I tried to do this, I missed a LOT.
First, when you create the class that hosts ExcelReturnString(), you need to decorate the class with an interface that has the following attributes and then also tag the attributes for each method you want to expose. I made the add-in class "TestExcelAddIn" for the sake of this example:
using System.Data;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace TestExcelAddIn
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IStringGetter
{
string ExcelReturnString();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class StringGetter : IStringGetter
{
public string ExcelReturnString()
{
return "This is the string: hi";
}
}
}
Then, in the main class, associated with "Excel" in your project, you have to override RequestComAddInAutomationService in the following manner. Again, I am including EVERYTHING so you know which class is which (I didn't when I first read it).
namespace TestExcelAddIn
{
public partial class ExcelTest
{
private StringGetter myAddIn;
protected override object RequestComAddInAutomationService()
{
if (myAddIn == null)
myAddIn = new StringGetter();
return myAddIn;
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
#endregion
}
}
Now VBA is ready to consume this method in the following manner:
Sub Test()
Dim addin As Office.COMAddIn
Dim automationObject As Object
Dim returnString As String
Set addin = Application.COMAddIns("TestExcelAddIn")
Set automationObject = addin.Object
returnString = automationObject.ExcelReturnString
End Sub
You could have given me 100 years to figure this out, and I would not have. Actually credit MSDN for the Rosetta stone on it:
https://msdn.microsoft.com/en-us/library/bb608621.aspx?f=255&MSPPError=-2147217396
In addition to DaveMac's note above, also keep in mind a couple of points when calling another routine:
If you're calling a macro from a routine that resides in the same workbook/addin as that routine, you don't have to use Application.Run. You can just call it by using its name:
MyMacro
If you're calling a macro that is in a different workbook, then you do need to use Application.Run, but you will also want to use the workbook name where the macro resides, otherwise VBA will not know where it should look for the macro:
Application.Run "'My Fancy Spreadsheet.xlsm!'MyMacro"
Your code appears to be java.
Excel uses Visual basic, for example.
Function excelreturnstring()
excelreturnstring = "this is the string: hi"
End function
I have written a class library. To execute methods that I wrote in my class library, I created a console application. In my console application, I added the class library that I wrote as a reference. I then added the appropriate using statement to my console application. My methods from this library are inaccessible currently. Why?
Here's my class library with a basic method. It was created in .NET framework 3.5.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geometry;
namespace RelateTablesValidation
{
[Guid("e1058544-0d84-49be-a406-b4e65707f95b")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("RelateTablesValidation.Validate")]
[ComVisible(true)]
public class Validate : ESRI.ArcGIS.Geodatabase.IClassExtension, ESRI.ArcGIS.Geodatabase.IObjectClassExtension, ESRI.ArcGIS.Geodatabase.IRelatedObjectClassEvents2
{
public void ChangeClassExtension(IObjectClass objectClass, String extensionUID, IPropertySet extensionProperties)
{
ISchemaLock schemaLock = (ISchemaLock)objectClass;
try
{
// Attempt to get an exclusive schema lock.
schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
// Cast the object class to the IClassSchemaEdit2 interface.
IClassSchemaEdit2 classSchemaEdit = (IClassSchemaEdit2)objectClass;
if (!String.IsNullOrEmpty(extensionUID))
{
// Create a unique identifier (UID) object and change the extension.
UID extUID = new UIDClass();
extUID.Value = extensionUID;
classSchemaEdit.AlterClassExtensionCLSID(extUID, extensionProperties);
}
else
{
// Clear the class extension.
classSchemaEdit.AlterClassExtensionCLSID(null, null);
}
}
catch (COMException comExc)
{
throw new Exception("Could not change class extension.", comExc);
}
finally
{
schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}
}
}
Here's my console app. RelateTablesValidation is the class library. Also created in .NET Framework 3.5
using System;
using System.Collections.Generic;
using System.Text;
using RelateTablesValidation;
using Esri.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DatasourcesGDB;
namespace ApplyClassExtension
{
class Program
{
[STAThread()]
static void Main(string[] args)
{
//system sees objects from this namespace OK
IWorkspaceFactory workspaceFactory = new FileGDBWorkspaceFactory();
//now when i try to call my method, it doesn't even show up in Intellisense
ChangeClassExtension(method params would go here);
}
}
}
You can't do what you're trying to do.
All methods in C# are inside of objects. You must either make the method static and call it like this:
Validate.ChangeClassExtension(...);
Or don't make it static and instantiate an instance of Validate:
var val = new Validate();
val.ChangeClassExtension(...);
I'm new to programming and I have this script that I'm making, it makes a function that reads XML files based on your input, I've just ran into this issue though where I cannot access the variable named "XMLtext", it's public, can someone tell me what I'm doing wrong and explain it, I've tried various things.
using UnityEngine;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
using System.Collections;
public class Data : MonoBehaviour {
public TextAsset XMLtext;
void Main () {
}
public static string XMLread (params string[] no) {
var XMLfile = XDocument.Parse ();
var a = Data.XMLfile.Element ("data");
for (int i = 0; no[i] == null; i++) {
}
}
}
The problem is that your class Data, which owns the XMLtext field is an instance class. Your method XMLread is static, meaning it is shared across all instances of Data. To solve your problem either make XMLText static or make XMlread an instance method by removing the static keyword.
The problem is that your XMLtext field belongs to an instance of Data, while your XMLread method is static, so it belongs to the class Data. You probably just want to remove the static from XMLread, so that you're always in an instance of Data.