I have a Silverlight 5.0 application and prvoide MS Word Automation functionality where the user can edit/add new document. I have gone through to MSDN pages but couldn't find any event that MS Word triggers after saving the document. The only event that talks about saving is the "DocumentBeforeSave" event that dosen't helps. I need to know when the MS Word finishes saving the document so that is it ready to save to server.
Can someone help me with this?
Any idea is very much approciated.
using MSWord = Microsoft.Office.Interop.Word;
namespace ConsoleApplication4
{
class Program
{
static void Main()
{
var app = new MSWord.Application();
var doc = app.Documents.Open(#"..\..\myDoc.docx");
app.DocumentBeforeSave += app_DocumentBeforeSave;
}
static void app_DocumentBeforeSave(MSWord.Document Doc, ref bool SaveAsUI, ref bool Cancel)
{
app.DocumentBeforeSave -= app_DocumentBeforeSave;
Cancel = true;
Doc.Save();
if(Doc.Saved){
//Now you know the document has saved
}
app.DocumentBeforeSave += app_DocumentBeforeSave;
}
}
}
The Save method doesn't run on a seperate thread, so it only returns once the Save is complete.
The DocumentBeforeSave event takes in a boolean call Cancel this is passed with the ref parameter, and setting it to true cancels the save that is about to take place.
You could set this to true, and then call Save yourself, this way you will know when the save has completed, as it runs on the same thread, something like this:
using MSWord = Microsoft.Office.Interop.Word;
namespace ConsoleApplication41
{
class Program
{
static void Main()
{
var app = new MSWord.Application();
var doc = app.Documents.Open(#"..\..\myDoc.docx");
app.DocumentBeforeSave += app_DocumentBeforeSave;
}
static void app_DocumentBeforeSave(MSWord.Document Doc, ref bool SaveAsUI, ref bool Cancel)
{
Cancel = true;
Doc.Save();
//Now you know the document has saved
}
}
}
Related
I'm working on a wpf app. visual studio 2022
I have the following code in a file for testing and have set a button click event to run WriteWorkOrderList(). nothing gets passed to it: there are no other methods or anything:
private List<Models.WorkOrder> _workOrderList = new List<Models.WorkOrder>();
public List<Models.WorkOrder> WorkOrderList
{
get
{
return _workOrderList;
}
set
{
if (_workOrderList != value)
{
_workOrderList = value;
NotifyPropertyChanged();
}
}
}
private Models.WorkOrder _currentWorkOrder = new Models.WorkOrder();
public Models.WorkOrder CurrentWorkorder
{
get
{
return _currentWorkOrder;
}
set
{
if (_currentWorkOrder != value)
{
_currentWorkOrder = value;
NotifyPropertyChanged();
}
}
}
public void WriteWorkOrderList()
{
CurrentWorkorder.Customer.Name = "Billy";
WorkOrderList.Add(CurrentWorkorder);
}
I placed a Breakpoint at the beginning of the WriteWorkOrderList()
method
I'll let it continue the first time. and get one record in
WorkOrderList with Customer.Name=Billy.
the second time I click the
button and get to the breakpoint I will change the
CurrentWorkOrder.Customer.Name= "joe".
I'll Step through the code
as soon as the line CurrentWorkorder.Customer.Name = "Billy"; gets processed the record in WorkOrderList updates to the new name
I can't figure out how they are connecting to each other. All I'm trying to do is add a new WorkOrder to the Workorderlist but I haven't Even gotten that far
I need to Delete All the records in a list applet by a button clicked method. In order to achieve this, I have added a button to the list applet with "DeleteAllRecords" method and added a script to BC PreInvokeMethod function as below. Once clicked on the button all the records will get deleted, but the applet won't get refreshed. How Can I achieve that?
try
{
if(MethodName == "DeleteAllRecords")
{
var EmpBO = TheApplication().GetBusObject("XXXX");
var EmpBC = EmpBO.GetBusComp("XXXX");
with(EmpBC)
{
SetViewMode(AllView);
ActivateField("EmployeeID");
ClearToQuery();
SetSearchExpr("[XXXX] <> ' '");
ExecuteQuery(ForwardOnly);
var Frecord = FirstRecord();
while(Frecord)
{
Frecord = DeleteRecord();
Frecord = FirstRecord();
}
}
//BC.InvokeMethod("RefreshBuscomp");
return (CancelOperation);
}
}
catch(e)
{
throw(e);
}
finally
{
EmpBO = null;
EmpBC = null;
}
return (ContinueOperation);
You could try a few things.
1: A simple null query in the end after all deletions are done. ClearToQuery() and ExecuteQuery();
2: There is a BC method for RefreshBusComp (check documentation) which can be used with InvokeMethod(). Does pretty much the same thing as 1. I see you already tried it and probably did not work.
3: There are Business services which can refresh applets , like FINS Teller UI navigation.
4: You could also try a null query in browserscript/javascript, put that in InvokeMethod, so that it runs after the BC escript. Genb has to be run to generate bscripts.
One of these should work .
I have an Single-document Interface(SDI) Microsoft Foundation Class(MFC) app that has to load a big document file (takes about 2 minutes). For that reason, my app stays unresponsive while I am opening the document.
However, I would like my app to be responsive while opening the document. The problem is that, if I try to load my document on a thread, my OnopenDocument function (in my doc) will return before I actually open the document:
BOOL CmodguiDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
start_tread(_open_doc); // just an example
return TRUE; // Will return before the document will actually be open
}
How can I do this to be non-locking but only returning after the document is actually open? Or how can I at least make my app responsive while I am loading the document?
Thanks
Returning after the thread has been created is OK. You should define a state for the document such as loading and loaded. When you start the thread the state should be loading. The view(s) should look at the state and display accordingly. When the thread has finished loading the document it should post a message to the document. In the handler, set the state to loaded and call UpdateAllViews() to give the views the chance to update with the new document data.
Example: This will print "loading" while the doc is loading and "loaded" and loaded after it finished in the view.
In resource.h:
#define IDD_NotifyDocumentFinished 101
In the document header:
public:
enum DocState
{
None,
Failed,
Loading,
Loaded
};
DocState GetDocState() const {return m_state;}
private:
DocState m_state;
void StartLoading();
In the document implementation:
BOOL CMFCDocViewAsyncDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if(!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
m_state = Loading;
StartLoading();
return TRUE;
}
UINT LongRunningFunction(LPVOID param)
{
Sleep(3000);
HWND hWnd = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
NMHDR hdr = {hWnd, IDD_NotifyDocumentFinished, 0};
::SendMessage(hWnd, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&hdr));
return 0;
}
void CMFCDocViewAsyncDoc::StartLoading()
{
AfxBeginThread(&LongRunningFunction, nullptr);
}
BOOL CMFCDocViewAsyncDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(HIWORD(nCode) == WM_NOTIFY)
{
WORD wCode = LOWORD(nCode);
AFX_NOTIFY * notify = reinterpret_cast<AFX_NOTIFY*>(pExtra);
if(notify->pNMHDR->idFrom == IDD_NotifyDocumentFinished)
{
m_state = Loaded;
UpdateAllViews(nullptr);
}
}
return TRUE;
}
In the view:
void CMFCDocViewAsyncView::OnDraw(CDC* pDC)
{
CMFCDocViewAsyncDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CMFCDocViewAsyncDoc::DocState state = pDoc->GetDocState();
CString sstate;
switch(state)
{
case CMFCDocViewAsyncDoc::None:
sstate = "None";
break;
case CMFCDocViewAsyncDoc::Failed:
sstate = "Failed";
break;
case CMFCDocViewAsyncDoc::Loading:
sstate = "Loading";
break;
case CMFCDocViewAsyncDoc::Loaded:
sstate = "Loaded";
break;
}
pDC->TextOut(50, 50, sstate);
}
Update: Also look here for a similar, more detailed example http://www.codeproject.com/Articles/14706/Notifying-the-Document.
When it takes two minutes to just load something, then there are two reasons for that:
You are doing something stupid while loading, like e.g. running expensive algorithms on the data like indexing or graphical rendering. If you store the data in containers, the overhead of allocations could also become significant. If that is the case, only perform them on demand or perform these operations asynchronously in the background. You can notify the main thread (the one running the UI) when done in order to display the rendered graphics, for example.
The data is incredibly large. In that case, you will have to rethink how to access this data anyway, because any operation might be expensive. Your best bet will be to use an asynchronous model, like sending a request to the model to perform some operation. The model then sends a response to the UI to display the data. In that case, you need to think about how to make this transparent to the user though. One approach is to darken the display area after a change request and only brighten it up after the response or a progress bar.
I have an app with contextual commands. After triggered a contextual command, it will make a HTTP request with a link and post the result on the card, something like, "Completed!". I want this card to be closed by itself after one second so that the user need not to tap to close it. Once the result card is closed, it will go back to contextual command lists with "Ok, glass" at footer and ready for next command.
May i know how to do that?
private class HTTPRequest extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
try {
if (mWhat.equalsIgnoreCase("GET")) {
// get json via YouTube API
URL url = new URL("http://example.com");
mUrlConnection = (HttpURLConnection)
url.openConnection();
InputStream in = new BufferedInputStream(
mUrlConnection.getInputStream());
int ch;
StringBuffer b = new StringBuffer();
while ((ch = in.read()) != -1) {
b.append((char) ch);
}
mResult = new String(b);
}
} catch (Exception e) {}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
mTvInfo.setText(mResult);
}
You can use an Android Dialog for this:
Use CardBuilder to create the "Completed" card using the MENU layout.
Create a new instance of Dialog and set its content view to be the view returned by CardBuilder.getView.
Show the dialog.
Use Handler.postDelayed (or some similar mechanism) to automatically dismiss the dialog after the desired amount of time has passed.
I am executing some commands on linux using JSCH and taking output of that command and printing same on the activity log in my JAVAFX application.
Here is a problem: the activity log area is getting stuck after printing some line. But, if I switch from the window and back application continues to print lines on log area. I have debugged several times but wasn't able to catch the problem.
Below is the code
channel.connect();
PrintStream commander = new PrintStream(channel.getOutputStream(), true);
commander.println(command_cd);
commander.println(" exit;");
commander.close();
InputStream outputstream_from_the_channel = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
String jarOutput;
BufferedWriter bw = new BufferedWriter(new FileWriter(resultLogFile.getAbsolutePath(), true));
while ((jarOutput = reader.readLine()) != null) {
this.logger.info("Status Update = " + jarOutput);
System.out.print("Status Update on screen ="+jarOutput + "\n");
bw.write(jarOutput);
bw.newLine();
outputFromUnix.append(jarOutput).append("\n");
// Display in activity log area in realtime.
if (DeploymentTaskController.actLogTArea != null) {
System.out.println("outputFromUnix.toString()---->>>>> " + outputFromUnix.toString());
//actlogArea is TextArea
DeploymentTaskController.actLogTArea.setText(outputFromUnix.toString());
DeploymentTaskController.actLogTArea.end();
}
}
bw.close();
reader.close();
JavaFX has a special thread named "JavaFX Application Thread" to update all UI. This thread shouldn't be used for any non-UI operations, and all UI operations must be run on that thread.
Make sure you run your code in a separate Thread and wrap all UI code into Platform#runLater() to have executed
// Using separate thread to run data loading code
new Thread(new Runnable() {
public void run() {
channel.connect();
// [...] all your channel reading code
// Updating UI from JavaFX Application Thread
if (DeploymentTaskController.actLogTArea != null) {
System.out.println("outputFromUnix.toString()---->>>>> " + outputFromUnix.toString());
final String outputStr = outputFromUnix.toString();
Platform.runLater(new Runnable() {
#Override
public void run() {
DeploymentTaskController.actLogTArea.setText(outputStr);
DeploymentTaskController.actLogTArea.end();
}
});
}
bw.close();
reader.close();
}
}).start();
There is also a special concurrency API in JavaFX for such tasks, see here: http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm