///<summary>Either a proc or a problem will be sent in, the other will be null.  If probCur then Procedure, Order: item, if procCur then Procedure, Perforemed: item.</summary>
		private static void GenerateProcedureEntry(EhrCqmProc procCur,EhrCqmProblem probCur) {
			_isWriterW=false;
			Start("entry","typeCode","DRIV");
			if(probCur!=null) {
				Start("procedure","classCode","PROC","moodCode","RQO");
				_x.WriteComment("Plan of Care Activity Procedure Template");
				TemplateId("2.16.840.1.113883.10.20.22.4.41");
				_x.WriteComment("QRDA Procedure Order Template");
				TemplateId("2.16.840.1.113883.10.20.24.3.63");
				StartAndEnd("id","root",_strOIDInternalCQMRoot,"extension",CqmItemAbbreviation.Prob.ToString()+probCur.EhrCqmProblemNum.ToString());
				Start("code","code",probCur.CodeValue,"displayName",probCur.Description,"codeSystem",probCur.CodeSystemOID,"codeSystemName",probCur.CodeSystemName);
				_x.WriteAttributeString("sdtc","valueSet",null,probCur.ValueSetOID);
				End("code");
				_x.WriteElementString("text","Procedure, Order: "+probCur.ValueSetName);
				StartAndEnd("statusCode","code","completed");
				_x.WriteComment("Attribute: datetime");
				Start("author");
				TimeElement("time",probCur.DateStart);
				Start("assignedAuthor");
				StartAndEnd("id","nullFlavor","NA");
				End("assignedAuthor");
				End("author");
				End("procedure");
			}
			if(procCur!=null) {
				Start("procedure","classCode","PROC","moodCode","EVN");
				_x.WriteComment("Procedure Activity Procedure Template");
				TemplateId("2.16.840.1.113883.10.20.22.4.14");
				_x.WriteComment("Procedure Performed Template");
				TemplateId("2.16.840.1.113883.10.20.24.3.64");
				StartAndEnd("id","root",_strOIDInternalCQMRoot,"extension",CqmItemAbbreviation.Proc.ToString()+procCur.EhrCqmProcNum.ToString());
				Start("code","code",procCur.ProcCode,"displayName",procCur.Description,"codeSystem",procCur.CodeSystemOID,"codeSystemName",procCur.CodeSystemName);
				_x.WriteAttributeString("sdtc","valueSet",null,procCur.ValueSetOID);
				End("code");
				_x.WriteElementString("text","Procedure, Performed: "+procCur.ValueSetName);
				StartAndEnd("statusCode","code","completed");
				Start("effectiveTime");
				_x.WriteComment("Attribute: Start Datetime");
				DateElement("low",procCur.ProcDate);
				_x.WriteComment("Attribute: Stop Datetime");
				DateElement("high",procCur.ProcDate);
				End("effectiveTime");
				End("procedure");
			}
			End("entry");
			_isWriterW=true;
		}
		///<summary>Get all procedures with ProcDate in the date range and ProcCode in the list of codes that belong to one of the value sets in listValueSetOIDs.</summary>
		private static Dictionary<long,List<EhrCqmProc>> GetProcs(List<long> listPatNums,List<string> listValueSetOIDs,DateTime dateStart,DateTime dateEnd) {
			Dictionary<long,List<EhrCqmProc>> retval=new Dictionary<long,List<EhrCqmProc>>();
			//if no patients, return a new empty dictionary
			if(listPatNums!=null && listPatNums.Count==0) {
				return retval;
			}
			List<EhrCode> listValidProcs=EhrCodes.GetForValueSetOIDs(listValueSetOIDs,false);
			string codeList="";
			for(int i=0;i<listValidProcs.Count;i++) {
				if(i>0) {
					codeList+=",";
				}
				codeList+="'"+listValidProcs[i].CodeValue+"'";
			}
			string command="SELECT procedurelog.ProcNum,procedurelog.PatNum,procedurelog.ProvNum,procedurelog.ProcDate,"
				+"procedurecode.ProcCode,procedurecode.Descript FROM procedurelog "
				+"INNER JOIN procedurecode ON procedurelog.CodeNum=procedurecode.CodeNum "
				+"WHERE procedurelog.ProcStatus=2 "
				+"AND procedurelog.ProcDate BETWEEN "+POut.Date(dateStart)+" AND "+POut.Date(dateEnd)+" ";
			if(listPatNums!=null && listPatNums.Count>0) {
				command+="AND procedurelog.PatNum IN ("+string.Join(",",listPatNums)+")";
			}
			if(codeList!="") {
				command+="AND procedurecode.ProcCode IN("+codeList+") ";
			}
			command+="ORDER BY procedurelog.PatNum,procedurelog.ProcDate DESC";
			DataTable tableAllProcs=Db.GetTable(command);
			if(tableAllProcs.Rows.Count==0) {
				return retval;
			}
			Dictionary<long,EhrCode> dictProcNumEhrCode=new Dictionary<long,EhrCode>();
			for(int i=tableAllProcs.Rows.Count-1;i>-1;i--) {
				for(int j=0;j<listValidProcs.Count;j++) {
					if(tableAllProcs.Rows[i]["ProcCode"].ToString()==listValidProcs[j].CodeValue) {
						dictProcNumEhrCode.Add(PIn.Long(tableAllProcs.Rows[i]["ProcNum"].ToString()),listValidProcs[j]);
						break;
					}
				}
			}
			for(int i=0;i<tableAllProcs.Rows.Count;i++) {
				EhrCqmProc ehrProcCur=new EhrCqmProc();
				ehrProcCur.EhrCqmProcNum=PIn.Long(tableAllProcs.Rows[i]["ProcNum"].ToString());
				ehrProcCur.PatNum=PIn.Long(tableAllProcs.Rows[i]["PatNum"].ToString());
				ehrProcCur.ProvNum=PIn.Long(tableAllProcs.Rows[i]["ProvNum"].ToString());
				ehrProcCur.ProcDate=PIn.Date(tableAllProcs.Rows[i]["ProcDate"].ToString());
				ehrProcCur.ProcCode=tableAllProcs.Rows[i]["ProcCode"].ToString();
				ehrProcCur.Description=tableAllProcs.Rows[i]["Descript"].ToString();
				EhrCode ehrCodeCur=dictProcNumEhrCode[ehrProcCur.EhrCqmProcNum];
				ehrProcCur.CodeSystemName=ehrCodeCur.CodeSystem;
				ehrProcCur.CodeSystemOID=ehrCodeCur.CodeSystemOID;
				ehrProcCur.ValueSetName=ehrCodeCur.ValueSetName;
				ehrProcCur.ValueSetOID=ehrCodeCur.ValueSetOID;
				if(retval.ContainsKey(ehrProcCur.PatNum)) {
					retval[ehrProcCur.PatNum].Add(ehrProcCur);
				}
				else {
					retval.Add(ehrProcCur.PatNum,new List<EhrCqmProc>() { ehrProcCur });
				}
			}
			return retval;
		}