Author Topic: ...not declared. It may be inaccessible due to its protection level.  (Read 20806 times)

0 Members and 1 Guest are viewing this topic.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #15 on: October 31, 2011, 03:12:27 PM »
Thanks Jeff,  another question for you, when you did the test for open Excel, I got that perfectly.  Is there a test to see if the xlsx is open?  It appears to work perfectly if its open or not, I just want to make this rock solid. this is what I'm doing
Code: [Select]
Excel.Application xlApp;
            bool xLopen = false;
            try
            {
                xlApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
                xLopen = true;
            }
            catch
            {
                xlApp = new Microsoft.Office.Interop.Excel.Application();
            }
            Workbook wb = xlApp.Workbooks.Open(strMyFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            Worksheet ws = wb.Sheets["Sheet1"] as Worksheet;
            xlApp.Visible = true;
            xlApp.UserControl = true;
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #16 on: October 31, 2011, 03:13:43 PM »
BTW your example was perfect.  I had never used Marshal before, nor had I ever linked to another application.  I had only done it through VBA (ack)
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #17 on: October 31, 2011, 03:24:26 PM »
Here is the finished product at this point
Code: [Select]
[CommandMethod("PLog")]
        public static void ProjectLog()
        {
            Document doc = acApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string DwgPath = Path.GetDirectoryName(acApp.DocumentManager.MdiActiveDocument.Name);
            string ProjNum = DwgPath.Substring(DwgPath.LastIndexOf("\\") + 1);
            PromptSelectionOptions pso = new PromptSelectionOptions();
            TypedValue[] filter = new TypedValue[2] { new TypedValue((int)DxfCode.Start, "INSERT"), new TypedValue((int)DxfCode.BlockName, "VTEP-INFO,TEP-INFO,TEP-CIP,VTEP-CIP,VUES-INFO,UES-INFO,UES-CIP,VUES-CIP") };
            SelectionFilter selFilter = new SelectionFilter(filter);
            PromptSelectionResult psr = ed.SelectAll(selFilter);
            if (psr.Status != PromptStatus.OK)
            {
                acApp.ShowAlertDialog("Invalid Titleblock in drawing!");
                return;
            }
            string strDwgLine1 = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "TITLE1");
            string strDwgLine2 = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "TITLE2");
            string strDwgNum = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "NUM");
            string strDwgVendor = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "VENDORNAME");
            string strDwgVendorNumber = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "VENDORNUMBER");
            string strUserPath = GetUser(System.Environment.UserName);
            string strMyFile = string.Concat(strUserPath, "\\", ProjNum, "\\", ProjNum, ".xlsx");
            string strFilename = string.Concat(ProjNum + ".xlsx");

            Excel.Application xlApp;
            bool xLopen = false;
            try
            {
                xlApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
                xLopen = true;
            }
            catch
            {
                xlApp = new Microsoft.Office.Interop.Excel.Application();
            }

            Workbook wb = xlApp.Workbooks.Open(strMyFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            Worksheet ws = wb.Sheets["Sheet1"] as Worksheet;
            xlApp.Visible = true;
            xlApp.UserControl = true;

            Excel.Range currentFind = null;
            Excel.Range firstFind = null;

            currentFind = (Excel.Range)ws.Columns["B", Type.Missing];

            firstFind = currentFind.Find(strDwgNum, Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlWhole, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, 0, 0, Type.Missing);
            string foundAddress = firstFind.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);
            firstFind.Activate();
            int rowNum = firstFind.Row;

            if (!string.IsNullOrEmpty(strDwgVendor))
            {
                ws.Cells[rowNum, 5] = strDwgLine1 + "," + strDwgLine2 + "/" + strDwgVendor + "," + strDwgVendorNumber;
            }
            else
            {
                ws.Cells[rowNum, 5] = strDwgLine1 + "," + strDwgLine2;
            }
            ws.Cells[rowNum, 1] = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "SHT");
            ws.Cells[rowNum, 3] = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "REV");
            ws.Cells[rowNum, 4] = GetAttributeValueFromBlock(db, psr.Value.GetObjectIds()[0], "CODE");
            if (xLopen)
            {
                wb.Save();
            }
            else
            {
                wb.Close(true, Type.Missing, Type.Missing);
                xlApp.Quit();
            }
            Marshal.FinalReleaseComObject(xlApp);
        }

and the helper methods
Code: [Select]
public static string GetAttributeValueFromBlock(Database db, ObjectId blockRefId, string attName)
{
  string textString = null;
  using (Transaction tr = db.TransactionManager.StartTransaction())
  {
    BlockReference blockRef = tr.GetObject(blockRefId, OpenMode.ForRead) as BlockReference;
    if (blockRef != null)
    {
      foreach (ObjectId id in blockRef.AttributeCollection)
      {
        AttributeReference attRef = tr.GetObject(id, OpenMode.ForRead) as AttributeReference;
        if ((attRef != null) && (attRef.Tag.ToUpper() == attName))
         {
            textString = attRef.TextString;
            break;
         }
        }
      }
    tr.Commit();
    }
  return textString;
}
private static string GetUser(string User)
{
switch (User.ToUpper())
{
case "UA02038":
return @"\\tuslpna01\autocad\Reproductions_Area\000-Hall";
default:
return @"No Path Defined";
}
« Last Edit: October 31, 2011, 03:29:31 PM by CmdrDuh »
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #18 on: October 31, 2011, 04:00:48 PM »
Is there a test to see if the xlsx is open? 
Not sure if you mean excel(using a method instead try block?) or the file.
I forgot to add logic if it is not the Active workbook.
Code: [Select]
        [CommandMethod("OpenExcelEarlyBind")]
        public void OpenExcelEarlyBind()
        {         
            ExcelApp.Application exl;
            if (IsExcelRunning())
            {
                exl = (ExcelApp.Application)Marshal.GetActiveObject("Excel.Application");               
            }
            else
            {
                exl = new Microsoft.Office.Interop.Excel.Application();
               
            }
            exl.Visible = true;

            if (exl.Workbooks.Count < 1 )
            {
                exl.Workbooks.Open(@"C:\Test\ExcelTest.xlsx");
            }
           
           ///////Will crash if you check and no workbooks are open and reason for precvious staement
            if (exl.Workbooks[exl.Workbooks.Count].Name != "ExcelTest.xlsx")
            {
                exl.Workbooks.Open(@"C:\Test\ExcelTest.xlsx");
            }             
           
            ExcelApp.Worksheet ws = exl.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;     

            ws.Range["A1"].Value = DateTime.Now.ToLongTimeString();
            Marshal.FinalReleaseComObject(exl);
        }

        bool IsExcelRunning()
        {
            Process[] pros = Process.GetProcesses();
            foreach (var process in pros)
            {
                if (process.ProcessName == "EXCEL")
                {
                    return true;
                }
            }
            return false;
        }

 
 
 

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #19 on: October 31, 2011, 04:20:47 PM »
Well, at first, I meant the file, but now that I think about it, both.  I was able to make your code work perfectly, so today has been a success.

That being said, I was trying to make this work, but haven't quite gotten it figured out.
Code: [Select]
  xlApp = (Excel.Application )GetOrCreateInstance("Excel.Application");
static object GetInstance(string appName)
        {
            return Marshal.GetActiveObject(appName); 
        }
        static object CreateInstance(string appName)
        {
            return Activator.CreateInstance(Type.GetTypeFromProgID(appName));
        }
        static object GetOrCreateInstance(string appName)
        {
            try { return GetInstance(appName); }
            catch { return CreateInstance(appName); }
        }
« Last Edit: October 31, 2011, 04:50:05 PM by CmdrDuh »
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #20 on: October 31, 2011, 04:50:45 PM »
I got the above working, now to get my bool to work.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #21 on: October 31, 2011, 05:52:41 PM »
I just cant seem to make this work.  The else Activate is not working
 

Code: [Select]
if (!xLopen)
            {
                wb = xlApp.Workbooks.Open(strMyFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            }
            else
            {
                wb = Microsoft.Office.Interop.Excel.Workbooks[strFilename + "xlsx"].Activate();
            }
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #22 on: October 31, 2011, 06:37:31 PM »
Activate()  does not return a Workbook it is marked as void
 
Code: [Select]
            wb = xlApp.Workbooks[strFilename + "xlsx"];
            wb.Activate();

 
 

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2132
  • class keyThumper<T>:ILazy<T>
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #23 on: October 31, 2011, 08:36:03 PM »

Good thread guys !
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #24 on: November 01, 2011, 08:48:12 AM »
Well that makes sense.  Funny thing is I must have been using old or outdated code from MS b/c I was coping from MSDN I thought.  Off to make those changes.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #25 on: November 01, 2011, 11:20:58 AM »
This reminded me that I have been meaning to write something that made dealing with attributes easier.
Sometimes it makes life easier to wrap up complexity into small chunks so you do not have to think about too much at one time.
 
This is not a good one as I have not spent much time thinking about it and threw it together quickly,
 and would need help from all you guys anyway to have one that was worth using, but maybe this will spark ideas.
My first stab was getting the textstring values like a indexer method using 'AttributedTextInfo' class.
 
Code: [Select]
        [CommandMethod("TitleBlock")]
        public void TitleBlock()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction trx = db.TransactionManager.StartTransaction())
            {
                ObjectId brefId = ed.GetEntity("\nSelect Block").ObjectId;
                AttributedTextInfo atts = new AttributedTextInfo(brefId);
                string val = atts["Test"];
                Application.ShowAlertDialog(val);
                string val2 = atts["Test2"];
                Application.ShowAlertDialog(val2);
               
                trx.Commit();
            }                   
        }

Code that once it is designed correctly you should not think about it, have to look it, don't care about it, it just does what it suppose to etc.....
 
Code: [Select]
public class AttributedTextInfo : IEnumerable
    {
        private ObjectId _objectId;
        private Dictionary<string, string> _attributes;       
        public AttributedTextInfo(ObjectId brefId)
        {
            _objectId = brefId;
            _attributes = new Dictionary<string, string>();
            getAttributes();
        }
 
        private void getAttributes()
        {
            using (Transaction tr = _objectId.Database.TransactionManager.StartTransaction())
            {
                BlockReference blockRef = tr.GetObject(_objectId, OpenMode.ForRead) as BlockReference;
                if (blockRef != null)
                {
                    foreach (ObjectId id in blockRef.AttributeCollection)
                    {
                        AttributeReference attRef = tr.GetObject(id, OpenMode.ForRead) as AttributeReference;
                        if ((attRef != null))
                        {
                            _attributes.Add(attRef.Tag, attRef.TextString);
     
                        }
                    }
                }
                tr.Commit();
            }
        }
        public IEnumerator GetEnumerator()
        {
            return _attributes.GetEnumerator();
        }
        public string this[string tag]
        {
            get { return _attributes[tag.ToUpper()]; }
        }

    }

Pitfalls--no upadating values, could add logic for getting the val from definition to have a bool IsDefaultText, etc..........
 
 

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #26 on: May 23, 2012, 11:54:50 AM »
OK I know this is really old thread, but it does apply.  Jeff, I have been using your code, and it works great, but I can't seem to get the computer to let go of the EXCEL.EXE process.
Im using this: Marshal.FinalReleaseComObject(xlApp)


I step through the code, and watch that line get processed, but task manager still shows the process running.


I used this from you as well
Code: [Select]
public static bool IsExcelRunning()
        {
            Process[] pros = Process.GetProcesses();
            foreach (var process in pros)
            {
                if (process.ProcessName == "EXCEL")
                {
                    return true;
                }
            }
            return false;
        }




update - i was watching the task manager, and it did not let go of the process til I closed the dwg
« Last Edit: May 23, 2012, 12:04:29 PM by CmdrDuh »
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #27 on: May 23, 2012, 12:36:35 PM »
That great to hear to its been working okay as it was thrown together quickly and for example and already seeing better ways to implement it.
 
When scrolling down quickly my first thought was the variable at the class level holding the excel process might have something to do with it, but

Quote from: MSDN

The FinalReleaseComObject method releases the managed reference to a COM object. Calling this method is equivalent to calling the ReleaseComObject method in a loop until it returns 0 (zero).
When the reference count on the COM object becomes 0, the COM object is usually freed, although this depends on the COM object's implementation and is beyond the control of the runtime. However, the RCW can still exist, waiting to be garbage-collected.
LINK
 
When the drawing was closed it might have caused a GarbageCollection.
 
Just for testing and REMOVE after testing add
GC.Collect(2);
2 or 3 times and see if it ends.
 
Again Remove it.
 
« Last Edit: May 23, 2012, 12:40:53 PM by Jeff H »

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #28 on: May 23, 2012, 12:52:33 PM »
Well I added it 3 times like you suggested but it didn't go away til the dwg closed. argh, this is a pain.  The real pain is when I run a script to access many dwg files, the cpu runs too fast to let excel go away before it gets to the next dwg and creates excel again.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Jeff H

  • Needs a day job
  • Posts: 6150
Re: ...not declared. It may be inaccessible due to its protection level.
« Reply #29 on: May 23, 2012, 01:03:49 PM »
Are you calling Quit first?
Code - C#: [Select]
  1.  
  2. xlApp.Quit()
  3. Marshal.FinalReleaseComObject(xlApp)
  4.